@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.
Files changed (117) hide show
  1. package/dist/agent/index.cjs +8 -4
  2. package/dist/agent/index.js +6 -2
  3. package/dist/animation-editor/controller.d.cts +8 -0
  4. package/dist/animation-editor/controller.d.ts +8 -0
  5. package/dist/animation-editor/effect-tools.d.cts +1 -1
  6. package/dist/animation-editor/effect-tools.d.ts +1 -1
  7. package/dist/animation-editor/index.cjs +172 -105
  8. package/dist/animation-editor/index.js +91 -24
  9. package/dist/brushes/index.cjs +59 -59
  10. package/dist/brushes/index.js +5 -5
  11. package/dist/brushes/profiles.d.cts +6 -1
  12. package/dist/brushes/profiles.d.ts +6 -1
  13. package/dist/{brushstrokeRender-FSUWXUZY.cjs → brushstrokeRender-L7JYRR2R.cjs} +16 -16
  14. package/dist/{brushstrokeRender-KD453OBX.js → brushstrokeRender-NLFPEBGI.js} +4 -4
  15. package/dist/canvas/brushTypes.d.cts +12 -0
  16. package/dist/canvas/brushTypes.d.ts +12 -0
  17. package/dist/canvas/brushstroke.d.cts +1 -1
  18. package/dist/canvas/brushstroke.d.ts +1 -1
  19. package/dist/canvas/drawController.d.cts +19 -4
  20. package/dist/canvas/drawController.d.ts +19 -4
  21. package/dist/canvas/index.cjs +144 -105
  22. package/dist/canvas/index.js +46 -7
  23. package/dist/{chunk-XORJ7UZO.cjs → chunk-3VHH6V67.cjs} +13 -12
  24. package/dist/{chunk-T2LDTEXK.js → chunk-4IDUYB45.js} +2217 -56
  25. package/dist/chunk-7UKFXXWL.js +802 -0
  26. package/dist/chunk-ADMRNWR7.js +340 -0
  27. package/dist/{chunk-CIJBSUM5.js → chunk-AGNUD5BI.js} +2 -2
  28. package/dist/{chunk-WLUVZKVD.cjs → chunk-DT4YQUGT.cjs} +32 -32
  29. package/dist/{chunk-DXYHQ2VN.js → chunk-EF7LZAXQ.js} +1 -1
  30. package/dist/chunk-EXB2EGBE.cjs +802 -0
  31. package/dist/{chunk-4ODRXQRW.js → chunk-EYSHTYLG.js} +1 -1
  32. package/dist/{chunk-R44Y3EFS.js → chunk-FGJHJIMN.js} +8 -336
  33. package/dist/{chunk-AQZQWXEU.cjs → chunk-G7NHE2VD.cjs} +35 -35
  34. package/dist/{chunk-XC6DPRYI.js → chunk-GSTSZPSR.js} +154 -949
  35. package/dist/{chunk-VRK322ZC.cjs → chunk-HIO6E7LC.cjs} +2 -2
  36. package/dist/{chunk-TOID45I2.cjs → chunk-J2TNIZ55.cjs} +1 -1
  37. package/dist/{chunk-YHDHFJUC.cjs → chunk-J5VQYK7T.cjs} +217 -1012
  38. package/dist/{chunk-3C33YTNN.js → chunk-JGWVZPT6.js} +2 -2
  39. package/dist/{chunk-ACFSFUQH.js → chunk-JL6YH5WD.js} +4 -0
  40. package/dist/{chunk-3SBLVGOM.cjs → chunk-LA5Y4ETA.cjs} +23 -23
  41. package/dist/{chunk-MVUQSK5J.cjs → chunk-LHPEG5AU.cjs} +107 -435
  42. package/dist/{chunk-DOZ6F2K2.js → chunk-NSETJI74.js} +3 -2
  43. package/dist/{chunk-XRXFVRGY.cjs → chunk-OKHKA43L.cjs} +2364 -203
  44. package/dist/{chunk-LK4SXL3V.js → chunk-OSEXT7JL.js} +1 -1
  45. package/dist/{chunk-PE6YJMQT.cjs → chunk-PFHJS4HE.cjs} +20 -19
  46. package/dist/{chunk-ZQI3WUPP.js → chunk-QCLY5SFS.js} +12 -0
  47. package/dist/{chunk-7KNW3WXZ.cjs → chunk-QEVLRLUN.cjs} +63 -0
  48. package/dist/{chunk-OTN6VB5S.cjs → chunk-RDFHWAHL.cjs} +5 -1
  49. package/dist/{chunk-6JL2D5SG.js → chunk-VE6UKYQ2.js} +3 -2
  50. package/dist/{chunk-RFJZGTHA.cjs → chunk-XVOP3CGQ.cjs} +9 -9
  51. package/dist/{chunk-EZOJBP4D.js → chunk-YIC6MAJ2.js} +1 -1
  52. package/dist/chunk-YZWM6ZIP.cjs +340 -0
  53. package/dist/{chunk-472INMWH.js → chunk-ZA7L5YJB.js} +63 -0
  54. package/dist/{chunk-YBC3RKT2.cjs → chunk-ZGXJ7BTR.cjs} +13 -1
  55. package/dist/commands/builtins.d.cts +12 -1
  56. package/dist/commands/builtins.d.ts +12 -1
  57. package/dist/commands/index.cjs +2 -2
  58. package/dist/commands/index.js +1 -1
  59. package/dist/image-editor/controller.d.cts +1 -1
  60. package/dist/image-editor/controller.d.ts +1 -1
  61. package/dist/image-editor/index.cjs +837 -833
  62. package/dist/image-editor/index.js +105 -101
  63. package/dist/paint/index.cjs +5 -3
  64. package/dist/paint/index.js +46 -44
  65. package/dist/paint-editor/controller.d.cts +5 -3
  66. package/dist/paint-editor/controller.d.ts +5 -3
  67. package/dist/paint-editor/index.cjs +832 -2295
  68. package/dist/paint-editor/index.js +285 -1748
  69. package/dist/paint-editor/path-samples.d.cts +2 -0
  70. package/dist/paint-editor/path-samples.d.ts +2 -0
  71. package/dist/paint-editor/presence.d.cts +20 -1
  72. package/dist/paint-editor/presence.d.ts +20 -1
  73. package/dist/stickers/helpers.d.cts +2 -0
  74. package/dist/stickers/helpers.d.ts +2 -0
  75. package/dist/stickers/index.cjs +41 -35
  76. package/dist/stickers/index.js +22 -16
  77. package/dist/stickers/types.d.cts +4 -2
  78. package/dist/stickers/types.d.ts +4 -2
  79. package/dist/tools/conformance.d.cts +8 -0
  80. package/dist/tools/conformance.d.ts +8 -0
  81. package/dist/tools/index.cjs +6 -2
  82. package/dist/tools/index.js +5 -1
  83. package/dist/vector/backdrop.d.cts +13 -0
  84. package/dist/vector/backdrop.d.ts +13 -0
  85. package/dist/vector/brushstroke.d.cts +54 -7
  86. package/dist/vector/brushstroke.d.ts +54 -7
  87. package/dist/vector/brushstrokeMedia.d.cts +96 -0
  88. package/dist/vector/brushstrokeMedia.d.ts +96 -0
  89. package/dist/vector/controller.d.cts +17 -3
  90. package/dist/vector/controller.d.ts +17 -3
  91. package/dist/vector/index.cjs +1846 -1386
  92. package/dist/vector/index.d.cts +2 -0
  93. package/dist/vector/index.d.ts +2 -0
  94. package/dist/vector/index.js +517 -57
  95. package/dist/vector/render.d.cts +6 -0
  96. package/dist/vector/render.d.ts +6 -0
  97. package/dist/vector/types.d.cts +14 -0
  98. package/dist/vector/types.d.ts +14 -0
  99. package/package.json +1 -1
  100. package/skills/pixerate-animation-editor/SKILL.md +1 -0
  101. package/skills/pixerate-brushes/SKILL.md +2 -2
  102. package/skills/pixerate-brushes-design/SKILL.md +7 -4
  103. package/skills/pixerate-brushes-design/evals/port-to-vector.json +8 -8
  104. package/skills/pixerate-canvas/SKILL.md +11 -1
  105. package/skills/pixerate-image-editor/SKILL.md +19 -64
  106. package/skills/pixerate-image-editor/references/color-management.md +2 -1
  107. package/skills/pixerate-image-editor/references/free-transform.md +12 -0
  108. package/skills/pixerate-image-editor/references/layer-effects.md +10 -0
  109. package/skills/pixerate-image-editor/references/painting.md +17 -0
  110. package/skills/pixerate-image-editor/references/photoshop-files.md +1 -1
  111. package/skills/pixerate-image-editor/references/shapes-and-type.md +14 -0
  112. package/skills/pixerate-image-editor/references/smart-objects.md +10 -0
  113. package/skills/pixerate-paint-editor/SKILL.md +8 -4
  114. package/skills/pixerate-paint-editor/references/wet-media.md +9 -0
  115. package/skills/pixerate-vector/SKILL.md +16 -6
  116. package/skills/pixerate-vector/references/best-practices.md +1 -0
  117. package/skills/pixerate-vector/references/commands.md +19 -0
@@ -0,0 +1,340 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});// 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
+
335
+
336
+
337
+
338
+
339
+
340
+ exports.flattenPath = flattenPath; exports.flatBounds = flatBounds; exports.rasterizeCoverage = rasterizeCoverage; exports.rasterizeCoverageSampled = rasterizeCoverageSampled; exports.combineCoverage = combineCoverage;
@@ -382,9 +382,72 @@ function createDrawCommands(target, options = {}) {
382
382
  readOnly: true,
383
383
  run: async () => ({ brushes: await target.listBrushes() })
384
384
  },
385
+ ...createBrushChoiceCommands(target, base, prefix),
385
386
  ...createGestureCommands(target, base, prefix, options)
386
387
  ];
387
388
  }
389
+ function createBrushChoiceCommands(target, base, prefix) {
390
+ const { brushSettings, selectBrush, setColorLocked, setColorScheme } = target;
391
+ if (!brushSettings || !selectBrush || !setColorLocked || !setColorScheme) return [];
392
+ const settings = () => brushSettings();
393
+ const RESULT = "Returns { brush, color, colorScheme, colorLocked, colorFollowsScheme } (colorFollowsScheme: the colour is a brush's light / dark default and changes with the scheme).";
394
+ return [
395
+ {
396
+ ...base,
397
+ id: `${prefix}selectBrush`,
398
+ label: "Choose Pen Brush",
399
+ keywords: ["brush", "pen", "pick brush", "chalk", "pencil", "ink"],
400
+ description: `Chooses the brush the pen and highlighter draw with by hand (brushId from canvas.listBrushes, or null for a plain vector stroke), at the brush's own size. A brush with a default colour (the ballpoint's blue, the chalk's light / dark pair) makes it the stroke colour unless keepColour or the colour is locked (canvas.setColorLocked). Does not draw; canvas.drawFreehand takes its own brush. ${RESULT}`,
401
+ params: {
402
+ type: "object",
403
+ additionalProperties: false,
404
+ required: ["brushId"],
405
+ properties: {
406
+ brushId: { type: ["string", "null"], minLength: 1, description: "A brush id from canvas.listBrushes, or null for a plain vector stroke." },
407
+ keepColour: { type: "boolean", description: "Keep the current stroke colour this once instead of taking the brush's default colour (default false)." }
408
+ }
409
+ },
410
+ run: async (_ctx, params) => {
411
+ await selectBrush(params.brushId, params.keepColour ? { keepColour: true } : {});
412
+ return settings();
413
+ }
414
+ },
415
+ {
416
+ ...base,
417
+ id: `${prefix}setColorLocked`,
418
+ label: "Keep My Colour",
419
+ keywords: ["lock colour", "keep colour", "brush colour", "color lock"],
420
+ description: `Locks or unlocks the stroke colour ("Keep my colour"): while locked, canvas.selectBrush keeps the current colour instead of taking a brush's default colour. ${RESULT}`,
421
+ params: {
422
+ type: "object",
423
+ additionalProperties: false,
424
+ required: ["locked"],
425
+ properties: { locked: { type: "boolean", description: "true locks the colour, false unlocks it (the canvas starts unlocked)." } }
426
+ },
427
+ run: (_ctx, params) => {
428
+ setColorLocked(params.locked);
429
+ return settings();
430
+ }
431
+ },
432
+ {
433
+ ...base,
434
+ id: `${prefix}setColorScheme`,
435
+ label: "Brush Colours for Light / Dark",
436
+ keywords: ["colour scheme", "dark mode", "light mode", "theme", "brush colour"],
437
+ description: `Sets the colour scheme that picks the side of a brush's light / dark default colour (white chalk in dark, dark chalk in light). A stroke colour that came from such a default follows; strokes already drawn keep theirs, and canvas.drawFreehand resolves brush defaults for this scheme. The host usually sets it to match its theme. ${RESULT}`,
438
+ params: {
439
+ type: "object",
440
+ additionalProperties: false,
441
+ required: ["scheme"],
442
+ properties: { scheme: { type: "string", enum: ["light", "dark"], description: "light (dark chalk on a light background) or dark (light chalk on a dark one)." } }
443
+ },
444
+ run: (_ctx, params) => {
445
+ setColorScheme(params.scheme);
446
+ return settings();
447
+ }
448
+ }
449
+ ];
450
+ }
388
451
  var GESTURE_RECT_PARAM = {
389
452
  type: "object",
390
453
  additionalProperties: false,
@@ -727,6 +727,16 @@ function resultText(result) {
727
727
  }
728
728
  return void 0;
729
729
  }
730
+ var CONFORMANCE_NUMBER_TOLERANCE = 1e-9;
731
+ function conformanceValuesMatch(a, b) {
732
+ if (typeof a === "number" && typeof b === "number") return a === b || Math.abs(a - b) <= CONFORMANCE_NUMBER_TOLERANCE * Math.max(1, Math.abs(a), Math.abs(b));
733
+ if (Array.isArray(a) || Array.isArray(b)) return Array.isArray(a) && Array.isArray(b) && a.length === b.length && a.every((x, i) => conformanceValuesMatch(x, b[i]));
734
+ if (a && b && typeof a === "object" && typeof b === "object") {
735
+ const ka = Object.keys(a), kb = Object.keys(b);
736
+ return ka.length === kb.length && ka.every((k) => k in b && conformanceValuesMatch(a[k], b[k]));
737
+ }
738
+ return a === b;
739
+ }
730
740
  async function runConformanceScenario(scenario, host) {
731
741
  const ids = new ConformanceIds();
732
742
  const isId = _optionalChain([host, 'access', _41 => _41.isGeneratedId, 'optionalAccess', _42 => _42.bind, 'call', _43 => _43(host)]);
@@ -773,4 +783,6 @@ async function runConformanceScenario(scenario, host) {
773
783
 
774
784
 
775
785
 
776
- exports.listSkillEvals = listSkillEvals; exports.imageEvalFixturePixels = imageEvalFixturePixels; exports.callEvalTool = callEvalTool; exports.matchesEvalExpectation = matchesEvalExpectation; exports.failedEvalChecks = failedEvalChecks; exports.toolResultValue = toolResultValue; exports.toolResultError = toolResultError; exports.runToolScript = runToolScript; exports.parseStyleDomains = parseStyleDomains; exports.memoryStyleStore = memoryStyleStore; exports.createStyleResolver = createStyleResolver; exports.runStyleChecks = runStyleChecks; exports.renderStyle = renderStyle; exports.createStyleToolProvider = createStyleToolProvider; exports.createOriginMiddleware = createOriginMiddleware; exports.ConformanceIds = ConformanceIds; exports.CONFORMANCE_BINARY_MIN_LENGTH = CONFORMANCE_BINARY_MIN_LENGTH; exports.normalizeConformanceValue = normalizeConformanceValue; exports.omitConformancePaths = omitConformancePaths; exports.resolveConformanceArguments = resolveConformanceArguments; exports.conformanceResult = conformanceResult; exports.runConformanceScenario = runConformanceScenario;
786
+
787
+
788
+ exports.listSkillEvals = listSkillEvals; exports.imageEvalFixturePixels = imageEvalFixturePixels; exports.callEvalTool = callEvalTool; exports.matchesEvalExpectation = matchesEvalExpectation; exports.failedEvalChecks = failedEvalChecks; exports.toolResultValue = toolResultValue; exports.toolResultError = toolResultError; exports.runToolScript = runToolScript; exports.parseStyleDomains = parseStyleDomains; exports.memoryStyleStore = memoryStyleStore; exports.createStyleResolver = createStyleResolver; exports.runStyleChecks = runStyleChecks; exports.renderStyle = renderStyle; exports.createStyleToolProvider = createStyleToolProvider; exports.createOriginMiddleware = createOriginMiddleware; exports.ConformanceIds = ConformanceIds; exports.CONFORMANCE_BINARY_MIN_LENGTH = CONFORMANCE_BINARY_MIN_LENGTH; exports.normalizeConformanceValue = normalizeConformanceValue; exports.omitConformancePaths = omitConformancePaths; exports.resolveConformanceArguments = resolveConformanceArguments; exports.conformanceResult = conformanceResult; exports.CONFORMANCE_NUMBER_TOLERANCE = CONFORMANCE_NUMBER_TOLERANCE; exports.conformanceValuesMatch = conformanceValuesMatch; exports.runConformanceScenario = runConformanceScenario;
@@ -1,7 +1,7 @@
1
1
  import type { HistoryState } from '../history/types.cjs';
2
2
  import type { CanvasArrangeAction } from '../canvas/arrangeShortcuts.cjs';
3
3
  import type { AlignEdge, DistributeAxis, DistributeMode, ZOrderOperation } from '../canvas/arrange.cjs';
4
- import type { CanvasBrush, CanvasBrushPaint, CanvasBrushPreset } from '../canvas/brushTypes.cjs';
4
+ import type { CanvasBrush, CanvasBrushPaint, CanvasBrushPreset, CanvasBrushChoice } from '../canvas/brushTypes.cjs';
5
5
  import type { CommandSpec } from './registry.cjs';
6
6
  import type { PlaybackStep } from '../tools/playback.cjs';
7
7
  import { type ShortcutBinding } from './shortcuts.cjs';
@@ -133,6 +133,17 @@ export interface DrawCommandTarget {
133
133
  width: number;
134
134
  height: number;
135
135
  } | undefined;
136
+ /**
137
+ * The brush picker's state, for `canvas.selectBrush`, `canvas.setColorLocked` and
138
+ * `canvas.setColorScheme` (registered only when the target has all of these; the draw
139
+ * controller does).
140
+ */
141
+ brushSettings?(): CanvasBrushChoice;
142
+ selectBrush?(id: string | null, choice?: {
143
+ keepColour?: boolean;
144
+ }): Promise<CanvasBrushPreset | null>;
145
+ setColorLocked?(locked: boolean): void;
146
+ setColorScheme?(scheme: 'light' | 'dark'): void;
136
147
  }
137
148
  export interface DrawCommandOptions {
138
149
  /** Id prefix (default `canvas.`). */
@@ -1,7 +1,7 @@
1
1
  import type { HistoryState } from '../history/types.js';
2
2
  import type { CanvasArrangeAction } from '../canvas/arrangeShortcuts.js';
3
3
  import type { AlignEdge, DistributeAxis, DistributeMode, ZOrderOperation } from '../canvas/arrange.js';
4
- import type { CanvasBrush, CanvasBrushPaint, CanvasBrushPreset } from '../canvas/brushTypes.js';
4
+ import type { CanvasBrush, CanvasBrushPaint, CanvasBrushPreset, CanvasBrushChoice } from '../canvas/brushTypes.js';
5
5
  import type { CommandSpec } from './registry.js';
6
6
  import type { PlaybackStep } from '../tools/playback.js';
7
7
  import { type ShortcutBinding } from './shortcuts.js';
@@ -133,6 +133,17 @@ export interface DrawCommandTarget {
133
133
  width: number;
134
134
  height: number;
135
135
  } | undefined;
136
+ /**
137
+ * The brush picker's state, for `canvas.selectBrush`, `canvas.setColorLocked` and
138
+ * `canvas.setColorScheme` (registered only when the target has all of these; the draw
139
+ * controller does).
140
+ */
141
+ brushSettings?(): CanvasBrushChoice;
142
+ selectBrush?(id: string | null, choice?: {
143
+ keepColour?: boolean;
144
+ }): Promise<CanvasBrushPreset | null>;
145
+ setColorLocked?(locked: boolean): void;
146
+ setColorScheme?(scheme: 'light' | 'dark'): void;
136
147
  }
137
148
  export interface DrawCommandOptions {
138
149
  /** Id prefix (default `canvas.`). */
@@ -22,7 +22,7 @@ var _chunkKIJIONZFcjs = require('../chunk-KIJIONZF.cjs');
22
22
 
23
23
 
24
24
 
25
- var _chunk7KNW3WXZcjs = require('../chunk-7KNW3WXZ.cjs');
25
+ var _chunkQEVLRLUNcjs = require('../chunk-QEVLRLUN.cjs');
26
26
  require('../chunk-E2Z4UARJ.cjs');
27
27
 
28
28
 
@@ -413,4 +413,4 @@ function createCanvasAnimationCommands(controller, options = {}) {
413
413
 
414
414
 
415
415
 
416
- exports.CommandRegistry = _chunkKIJIONZFcjs.CommandRegistry; exports.CommandRegistryError = _chunkKIJIONZFcjs.CommandRegistryError; exports.DEFAULT_HISTORY_SHORTCUTS = _chunk7KNW3WXZcjs.DEFAULT_HISTORY_SHORTCUTS; exports.DEFAULT_RECENT_LIMIT = _chunkKIJIONZFcjs.DEFAULT_RECENT_LIMIT; exports.PLATFORMS = _chunkQJVOJUTDcjs.PLATFORMS; exports.ShortcutMap = _chunkQJVOJUTDcjs.ShortcutMap; exports.chordToString = _chunkQJVOJUTDcjs.chordToString; exports.codeFromKey = _chunkQJVOJUTDcjs.codeFromKey; exports.codeToKeyText = _chunkQJVOJUTDcjs.codeToKeyText; exports.createArrangeCommands = _chunk7KNW3WXZcjs.createArrangeCommands; exports.createCanvasAnimationCommands = createCanvasAnimationCommands; exports.createCommandPaletteController = createCommandPaletteController; exports.createCommandRegistry = _chunkKIJIONZFcjs.createCommandRegistry; exports.createCommandToolProvider = _chunkKIJIONZFcjs.createCommandToolProvider; exports.createComponentCommands = _chunk7KNW3WXZcjs.createComponentCommands; exports.createDrawCommands = _chunk7KNW3WXZcjs.createDrawCommands; exports.createFormatCommands = _chunkVCL7CB56cjs.createFormatCommands; exports.createHistoryCommands = _chunk7KNW3WXZcjs.createHistoryCommands; exports.createShapeCommands = _chunk7KNW3WXZcjs.createShapeCommands; exports.createSpreadsheetCommands = _chunk7KNW3WXZcjs.createSpreadsheetCommands; exports.defineCommand = _chunkKIJIONZFcjs.defineCommand; exports.detectPlatform = _chunkQJVOJUTDcjs.detectPlatform; exports.effectiveChord = _chunkQJVOJUTDcjs.effectiveChord; exports.effectiveChordKey = _chunkQJVOJUTDcjs.effectiveChordKey; exports.eventCode = _chunkQJVOJUTDcjs.eventCode; exports.exactBonus = _chunkKIJIONZFcjs.exactBonus; exports.formatCommandsFor = _chunkVCL7CB56cjs.formatCommandsFor; exports.formatShortcut = _chunkQJVOJUTDcjs.formatShortcut; exports.fuzzyMatch = _chunkKIJIONZFcjs.fuzzyMatch; exports.fuzzyScore = _chunkKIJIONZFcjs.fuzzyScore; exports.hasVariantCommands = _chunk7KNW3WXZcjs.hasVariantCommands; exports.isEditableEventTarget = _chunkQJVOJUTDcjs.isEditableEventTarget; exports.keyToCode = _chunkQJVOJUTDcjs.keyToCode; exports.matchHistoryShortcut = _chunk7KNW3WXZcjs.matchHistoryShortcut; exports.matchPaletteHotkey = matchPaletteHotkey; exports.normalizeChord = _chunkQJVOJUTDcjs.normalizeChord; exports.parseChord = _chunkQJVOJUTDcjs.parseChord; exports.planFreehandPlayback = _chunk7KNW3WXZcjs.planFreehandPlayback; exports.pushRecent = _chunkKIJIONZFcjs.pushRecent; exports.rankCommands = _chunkKIJIONZFcjs.rankCommands; exports.shortcutCode = _chunkQJVOJUTDcjs.shortcutCode; exports.toShortcutBindings = _chunkQJVOJUTDcjs.toShortcutBindings;
416
+ exports.CommandRegistry = _chunkKIJIONZFcjs.CommandRegistry; exports.CommandRegistryError = _chunkKIJIONZFcjs.CommandRegistryError; exports.DEFAULT_HISTORY_SHORTCUTS = _chunkQEVLRLUNcjs.DEFAULT_HISTORY_SHORTCUTS; exports.DEFAULT_RECENT_LIMIT = _chunkKIJIONZFcjs.DEFAULT_RECENT_LIMIT; exports.PLATFORMS = _chunkQJVOJUTDcjs.PLATFORMS; exports.ShortcutMap = _chunkQJVOJUTDcjs.ShortcutMap; exports.chordToString = _chunkQJVOJUTDcjs.chordToString; exports.codeFromKey = _chunkQJVOJUTDcjs.codeFromKey; exports.codeToKeyText = _chunkQJVOJUTDcjs.codeToKeyText; exports.createArrangeCommands = _chunkQEVLRLUNcjs.createArrangeCommands; exports.createCanvasAnimationCommands = createCanvasAnimationCommands; exports.createCommandPaletteController = createCommandPaletteController; exports.createCommandRegistry = _chunkKIJIONZFcjs.createCommandRegistry; exports.createCommandToolProvider = _chunkKIJIONZFcjs.createCommandToolProvider; exports.createComponentCommands = _chunkQEVLRLUNcjs.createComponentCommands; exports.createDrawCommands = _chunkQEVLRLUNcjs.createDrawCommands; exports.createFormatCommands = _chunkVCL7CB56cjs.createFormatCommands; exports.createHistoryCommands = _chunkQEVLRLUNcjs.createHistoryCommands; exports.createShapeCommands = _chunkQEVLRLUNcjs.createShapeCommands; exports.createSpreadsheetCommands = _chunkQEVLRLUNcjs.createSpreadsheetCommands; exports.defineCommand = _chunkKIJIONZFcjs.defineCommand; exports.detectPlatform = _chunkQJVOJUTDcjs.detectPlatform; exports.effectiveChord = _chunkQJVOJUTDcjs.effectiveChord; exports.effectiveChordKey = _chunkQJVOJUTDcjs.effectiveChordKey; exports.eventCode = _chunkQJVOJUTDcjs.eventCode; exports.exactBonus = _chunkKIJIONZFcjs.exactBonus; exports.formatCommandsFor = _chunkVCL7CB56cjs.formatCommandsFor; exports.formatShortcut = _chunkQJVOJUTDcjs.formatShortcut; exports.fuzzyMatch = _chunkKIJIONZFcjs.fuzzyMatch; exports.fuzzyScore = _chunkKIJIONZFcjs.fuzzyScore; exports.hasVariantCommands = _chunkQEVLRLUNcjs.hasVariantCommands; exports.isEditableEventTarget = _chunkQJVOJUTDcjs.isEditableEventTarget; exports.keyToCode = _chunkQJVOJUTDcjs.keyToCode; exports.matchHistoryShortcut = _chunkQEVLRLUNcjs.matchHistoryShortcut; exports.matchPaletteHotkey = matchPaletteHotkey; exports.normalizeChord = _chunkQJVOJUTDcjs.normalizeChord; exports.parseChord = _chunkQJVOJUTDcjs.parseChord; exports.planFreehandPlayback = _chunkQEVLRLUNcjs.planFreehandPlayback; exports.pushRecent = _chunkKIJIONZFcjs.pushRecent; exports.rankCommands = _chunkKIJIONZFcjs.rankCommands; exports.shortcutCode = _chunkQJVOJUTDcjs.shortcutCode; exports.toShortcutBindings = _chunkQJVOJUTDcjs.toShortcutBindings;
@@ -22,7 +22,7 @@ import {
22
22
  hasVariantCommands,
23
23
  matchHistoryShortcut,
24
24
  planFreehandPlayback
25
- } from "../chunk-472INMWH.js";
25
+ } from "../chunk-ZA7L5YJB.js";
26
26
  import "../chunk-55ALHYJY.js";
27
27
  import {
28
28
  PLATFORMS,
@@ -2583,7 +2583,7 @@ export declare class ImageEditorController {
2583
2583
  */
2584
2584
  private checkPsdFonts;
2585
2585
  /**
2586
- * The document as an RGB PSD at its bit depth (8, 16 or 32) (PSB above 30 000 px) with real layers, groups, adjustment
2586
+ * The document as a PSD in its colour mode (RGB, CMYK or Lab) at its bit depth (PSB above 30 000 px) with real layers, groups, adjustment
2587
2587
  * layers and masks, in the source frame. Layer filters and parametric (depth) masks are baked
2588
2588
  * into pixels and masks, annotation layers are rasterized (in a browser; elsewhere they are left
2589
2589
  * out), and the merged image is our composite. `warnings` lists every such change.
@@ -2583,7 +2583,7 @@ export declare class ImageEditorController {
2583
2583
  */
2584
2584
  private checkPsdFonts;
2585
2585
  /**
2586
- * The document as an RGB PSD at its bit depth (8, 16 or 32) (PSB above 30 000 px) with real layers, groups, adjustment
2586
+ * The document as a PSD in its colour mode (RGB, CMYK or Lab) at its bit depth (PSB above 30 000 px) with real layers, groups, adjustment
2587
2587
  * layers and masks, in the source frame. Layer filters and parametric (depth) masks are baked
2588
2588
  * into pixels and masks, annotation layers are rasterized (in a browser; elsewhere they are left
2589
2589
  * out), and the merged image is our composite. `warnings` lists every such change.