@pixerate/editor 0.106.0 → 0.108.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/THIRD_PARTY_NOTICES.md +4 -0
- package/dist/animation-editor/index.cjs +39 -39
- package/dist/animation-editor/index.d.cts +1 -1
- package/dist/animation-editor/index.d.ts +1 -1
- package/dist/animation-editor/index.js +1 -1
- package/dist/{chunk-DS7KDKPX.js → chunk-3PHA3UKI.js} +2 -2
- package/dist/{chunk-ZID226ZG.cjs → chunk-FRD3FUXI.cjs} +172 -172
- package/dist/{chunk-ZID226ZG.cjs.map → chunk-FRD3FUXI.cjs.map} +1 -1
- package/dist/{chunk-67FRIOPZ.js → chunk-G4BIYE6R.js} +2 -2
- package/dist/{chunk-PV42JITT.cjs → chunk-HUFQD4CB.cjs} +44 -44
- package/dist/{chunk-PV42JITT.cjs.map → chunk-HUFQD4CB.cjs.map} +1 -1
- package/dist/{chunk-63EFQCT5.js → chunk-HUQ7EHVI.js} +1140 -371
- package/dist/chunk-HUQ7EHVI.js.map +1 -0
- package/dist/{chunk-4X5MIVCE.js → chunk-SOROZ2BF.js} +3 -3
- package/dist/{chunk-CRMAXIUV.cjs → chunk-SZ6KMZNM.cjs} +157 -8
- package/dist/chunk-SZ6KMZNM.cjs.map +1 -0
- package/dist/{chunk-WSTEXEKD.cjs → chunk-T3QZ6S47.cjs} +92 -92
- package/dist/{chunk-WSTEXEKD.cjs.map → chunk-T3QZ6S47.cjs.map} +1 -1
- package/dist/{chunk-KANRAHTL.cjs → chunk-UTEVPQTS.cjs} +1353 -584
- package/dist/chunk-UTEVPQTS.cjs.map +1 -0
- package/dist/{chunk-HEW6KDNI.js → chunk-WMBIJCHA.js} +155 -6
- package/dist/chunk-WMBIJCHA.js.map +1 -0
- package/dist/{compositor-Bc3PNP3C.d.cts → compositor-D92URMlm.d.cts} +1 -1
- package/dist/{compositor-BsYYllvR.d.ts → compositor-Kt_M4ruo.d.ts} +1 -1
- package/dist/{export-_m3Es4ru.d.cts → export-JGWQEPJn.d.cts} +3 -3
- package/dist/{export-iMrop3Jm.d.ts → export-a9bnF7Cl.d.ts} +3 -3
- package/dist/image-editor/index.cjs +627 -619
- package/dist/image-editor/index.cjs.map +1 -1
- package/dist/image-editor/index.d.cts +8 -8
- package/dist/image-editor/index.d.ts +8 -8
- package/dist/image-editor/index.js +12 -4
- package/dist/image-editor/index.js.map +1 -1
- package/dist/{mixer-C1M1Nua_.d.cts → mixer-5ziHU8OS.d.cts} +1 -1
- package/dist/{mixer-Cu5a9Bzd.d.ts → mixer-DNqiYXYQ.d.ts} +1 -1
- package/dist/paint/index.cjs +3 -3
- package/dist/paint/index.d.cts +2 -2
- package/dist/paint/index.d.ts +2 -2
- package/dist/paint/index.js +2 -2
- package/dist/paint-editor/index.cjs +365 -132
- package/dist/paint-editor/index.cjs.map +1 -1
- package/dist/paint-editor/index.d.cts +113 -8
- package/dist/paint-editor/index.d.ts +113 -8
- package/dist/paint-editor/index.js +249 -16
- package/dist/paint-editor/index.js.map +1 -1
- package/dist/raster/index.cjs +11 -3
- package/dist/raster/index.cjs.map +1 -1
- package/dist/raster/index.d.cts +4 -4
- package/dist/raster/index.d.ts +4 -4
- package/dist/raster/index.js +10 -2
- package/dist/{surface-BBJN9wxg.d.ts → surface-CkKOHGPm.d.cts} +20 -2
- package/dist/{surface-BBJN9wxg.d.cts → surface-CkKOHGPm.d.ts} +20 -2
- package/dist/{svg-Bj1MQFh6.d.cts → svg-ClVIG4T7.d.cts} +26 -2
- package/dist/{svg-vme0PLNo.d.ts → svg-SseJTIrA.d.ts} +26 -2
- package/dist/vector/index.cjs +977 -948
- package/dist/vector/index.cjs.map +1 -1
- package/dist/vector/index.d.cts +266 -7
- package/dist/vector/index.d.ts +266 -7
- package/dist/vector/index.js +427 -398
- package/dist/vector/index.js.map +1 -1
- package/package.json +1 -1
- package/skills/pixerate-image-editor/SKILL.md +50 -7
- package/skills/pixerate-paint-editor/SKILL.md +21 -1
- package/skills/pixerate-vector/SKILL.md +35 -5
- package/dist/chunk-63EFQCT5.js.map +0 -1
- package/dist/chunk-CRMAXIUV.cjs.map +0 -1
- package/dist/chunk-HEW6KDNI.js.map +0 -1
- package/dist/chunk-KANRAHTL.cjs.map +0 -1
- /package/dist/{chunk-DS7KDKPX.js.map → chunk-3PHA3UKI.js.map} +0 -0
- /package/dist/{chunk-67FRIOPZ.js.map → chunk-G4BIYE6R.js.map} +0 -0
- /package/dist/{chunk-4X5MIVCE.js.map → chunk-SOROZ2BF.js.map} +0 -0
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
|
|
7
|
-
var
|
|
7
|
+
var _chunkFRD3FUXIcjs = require('../chunk-FRD3FUXI.cjs');
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
|
|
@@ -17,7 +17,7 @@ var _chunkZID226ZGcjs = require('../chunk-ZID226ZG.cjs');
|
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
|
|
20
|
-
var
|
|
20
|
+
var _chunkT3QZ6S47cjs = require('../chunk-T3QZ6S47.cjs');
|
|
21
21
|
require('../chunk-MUUXNRU4.cjs');
|
|
22
22
|
|
|
23
23
|
|
|
@@ -35,7 +35,7 @@ require('../chunk-MUUXNRU4.cjs');
|
|
|
35
35
|
|
|
36
36
|
|
|
37
37
|
|
|
38
|
-
var
|
|
38
|
+
var _chunkHUFQD4CBcjs = require('../chunk-HUFQD4CB.cjs');
|
|
39
39
|
|
|
40
40
|
|
|
41
41
|
|
|
@@ -50,7 +50,16 @@ var _chunkPV42JITTcjs = require('../chunk-PV42JITT.cjs');
|
|
|
50
50
|
|
|
51
51
|
|
|
52
52
|
|
|
53
|
-
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
var _chunkSZ6KMZNMcjs = require('../chunk-SZ6KMZNM.cjs');
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
var _chunkEGFUVXKKcjs = require('../chunk-EGFUVXKK.cjs');
|
|
54
63
|
require('../chunk-DWGZUSES.cjs');
|
|
55
64
|
|
|
56
65
|
// src/paint-editor/noise.ts
|
|
@@ -400,7 +409,7 @@ function newPaintLayerId() {
|
|
|
400
409
|
return `pl${Date.now().toString(36)}${(nextId++).toString(36)}`;
|
|
401
410
|
}
|
|
402
411
|
function createPaintLayer(name, id = newPaintLayerId()) {
|
|
403
|
-
return { type: "pixel", id, name, visible: true, opacity: 1, blend: "normal", surface:
|
|
412
|
+
return { type: "pixel", id, name, visible: true, opacity: 1, blend: "normal", surface: _chunkSZ6KMZNMcjs.emptySurface.call(void 0, 4), offset: { x: 0, y: 0 } };
|
|
404
413
|
}
|
|
405
414
|
var PaintDocumentError = class extends Error {
|
|
406
415
|
constructor(message) {
|
|
@@ -468,12 +477,12 @@ function normalizePaintBrush(raw = {}, base) {
|
|
|
468
477
|
name: typeof raw.name === "string" && raw.name.trim() ? raw.name.trim().slice(0, 80) : b.name,
|
|
469
478
|
category: PAINT_BRUSH_CATEGORIES.includes(raw.category) ? raw.category : b.category,
|
|
470
479
|
engine: PAINT_BRUSH_ENGINES.includes(raw.engine) ? raw.engine : b.engine,
|
|
471
|
-
tip:
|
|
480
|
+
tip: _chunkHUFQD4CBcjs.normalizeBrush.call(void 0, { ...b.tip, ..._nullishCoalesce(raw.tip, () => ( {})) }),
|
|
472
481
|
grain: unit2(raw.grain, b.grain),
|
|
473
482
|
pressureSmoothing: range(raw.pressureSmoothing, 0, 0.95, b.pressureSmoothing),
|
|
474
483
|
rotation: BRUSH_ROTATIONS.includes(raw.rotation) ? raw.rotation : b.rotation,
|
|
475
484
|
dynamics: normalizeDynamics(_nullishCoalesce(raw.dynamics, () => ( {})), b.dynamics),
|
|
476
|
-
mixer:
|
|
485
|
+
mixer: _chunkHUFQD4CBcjs.normalizeMixer.call(void 0, { ...b.mixer, ..._nullishCoalesce(raw.mixer, () => ( {})) }),
|
|
477
486
|
loadsColor: typeof raw.loadsColor === "boolean" ? raw.loadsColor : b.loadsColor,
|
|
478
487
|
...raw.builtin ? { builtin: true } : {}
|
|
479
488
|
};
|
|
@@ -483,12 +492,12 @@ var BASE_BRUSH = {
|
|
|
483
492
|
name: "Round",
|
|
484
493
|
category: "custom",
|
|
485
494
|
engine: "dab",
|
|
486
|
-
tip: { ...
|
|
495
|
+
tip: { ..._chunkHUFQD4CBcjs.DEFAULT_BRUSH },
|
|
487
496
|
grain: 0,
|
|
488
497
|
pressureSmoothing: 0,
|
|
489
498
|
rotation: "fixed",
|
|
490
499
|
dynamics: { ...DEFAULT_DYNAMICS },
|
|
491
|
-
mixer: { ...
|
|
500
|
+
mixer: { ..._chunkHUFQD4CBcjs.DEFAULT_MIXER },
|
|
492
501
|
loadsColor: true
|
|
493
502
|
};
|
|
494
503
|
var builtin = (init) => ({ ...normalizePaintBrush(init), builtin: true });
|
|
@@ -865,7 +874,7 @@ var DryStroke = (_class5 = class {
|
|
|
865
874
|
}
|
|
866
875
|
|
|
867
876
|
|
|
868
|
-
__init12() {this.coverage = new (0,
|
|
877
|
+
__init12() {this.coverage = new (0, _chunkHUFQD4CBcjs.CoverageMap)()}
|
|
869
878
|
__init13() {this.dabCount = 0}
|
|
870
879
|
|
|
871
880
|
|
|
@@ -899,11 +908,11 @@ var DryStroke = (_class5 = class {
|
|
|
899
908
|
const hardness = this.brush.tip.hardness;
|
|
900
909
|
const grain = this.options.grain;
|
|
901
910
|
for (const d of dabs) {
|
|
902
|
-
const rect =
|
|
911
|
+
const rect = _chunkHUFQD4CBcjs.dabRect.call(void 0, d, hardness);
|
|
903
912
|
const n = rect.width * rect.height;
|
|
904
913
|
if (this.buf.length < n) this.buf = new Float32Array(n);
|
|
905
914
|
const vals = this.buf.subarray(0, n);
|
|
906
|
-
|
|
915
|
+
_chunkHUFQD4CBcjs.rasterizeDab.call(void 0, d, hardness, rect, vals);
|
|
907
916
|
if (this.depth > 0 && grain) {
|
|
908
917
|
for (let yy = 0, k = 0; yy < rect.height; yy++) {
|
|
909
918
|
const y = rect.y + yy + 0.5;
|
|
@@ -928,7 +937,7 @@ function toStrokePoint(p) {
|
|
|
928
937
|
|
|
929
938
|
// src/paint-editor/stroke.ts
|
|
930
939
|
function defaultTile(surface) {
|
|
931
|
-
const data = new Uint8ClampedArray(
|
|
940
|
+
const data = new Uint8ClampedArray(_chunkSZ6KMZNMcjs.TILE * _chunkSZ6KMZNMcjs.TILE * surface.channels);
|
|
932
941
|
if (surface.defaultValue) data.fill(surface.defaultValue);
|
|
933
942
|
return data;
|
|
934
943
|
}
|
|
@@ -967,7 +976,7 @@ var PaintStrokeSession = (_class6 = class {
|
|
|
967
976
|
if (brush.engine === "mixer") {
|
|
968
977
|
this.mixerSmoother = new PenSmoother(brush.tip.smoothing, brush.pressureSmoothing);
|
|
969
978
|
const load = init.mixerLoad;
|
|
970
|
-
for (let i = 0; i < this.copies.length; i++) this.mixers.push(new (0,
|
|
979
|
+
for (let i = 0; i < this.copies.length; i++) this.mixers.push(new (0, _chunkHUFQD4CBcjs.MixerStroke)(mixerTip(brush), brush.mixer, load, this.mixerTarget()));
|
|
971
980
|
} else {
|
|
972
981
|
this.dry = new DryStroke(brush, { grain: init.grain, paperDepth: init.paperDepth, seed: init.seed, copies: this.copies });
|
|
973
982
|
}
|
|
@@ -995,9 +1004,9 @@ var PaintStrokeSession = (_class6 = class {
|
|
|
995
1004
|
offset: this.init.offset,
|
|
996
1005
|
lockTransparency: this.init.lockTransparency,
|
|
997
1006
|
selection: null,
|
|
998
|
-
readTile: (tx, ty) => _nullishCoalesce(_optionalChain([this, 'access', _4 => _4.live, 'access', _5 => _5.get, 'call', _6 => _6(
|
|
1007
|
+
readTile: (tx, ty) => _nullishCoalesce(_optionalChain([this, 'access', _4 => _4.live, 'access', _5 => _5.get, 'call', _6 => _6(_chunkSZ6KMZNMcjs.tileKey.call(void 0, tx, ty)), 'optionalAccess', _7 => _7.data]), () => ( null)),
|
|
999
1008
|
writeTile: (tx, ty) => {
|
|
1000
|
-
const key =
|
|
1009
|
+
const key = _chunkSZ6KMZNMcjs.tileKey.call(void 0, tx, ty);
|
|
1001
1010
|
if (!this.touched.has(key)) {
|
|
1002
1011
|
const src = _nullishCoalesce(_optionalChain([this, 'access', _8 => _8.base, 'access', _9 => _9.tiles, 'access', _10 => _10.get, 'call', _11 => _11(key), 'optionalAccess', _12 => _12.data]), () => ( defaultTile(this.base)));
|
|
1003
1012
|
this.live.set(key, { data: new Uint8ClampedArray(src), uniform: null });
|
|
@@ -1035,14 +1044,14 @@ var PaintStrokeSession = (_class6 = class {
|
|
|
1035
1044
|
if (!this.dry) {
|
|
1036
1045
|
for (const key of this.fresh) this.live.set(key, { data: this.live.get(key).data, uniform: null });
|
|
1037
1046
|
this.fresh.clear();
|
|
1038
|
-
this.host.update(this.layerId, new (0,
|
|
1047
|
+
this.host.update(this.layerId, new (0, _chunkSZ6KMZNMcjs.TiledSurface)(ch, new Map(this.live), this.base.defaultValue), rects);
|
|
1039
1048
|
return;
|
|
1040
1049
|
}
|
|
1041
1050
|
const off = this.init.offset;
|
|
1042
1051
|
const regions = /* @__PURE__ */ new Map();
|
|
1043
1052
|
for (const r of rects) {
|
|
1044
|
-
for (const t of
|
|
1045
|
-
const key =
|
|
1053
|
+
for (const t of _chunkSZ6KMZNMcjs.tilesInRect.call(void 0, { x: r.x - off.x, y: r.y - off.y, width: r.width, height: r.height })) {
|
|
1054
|
+
const key = _chunkSZ6KMZNMcjs.tileKey.call(void 0, t.tx, t.ty);
|
|
1046
1055
|
const cur = regions.get(key);
|
|
1047
1056
|
regions.set(key, { tx: t.tx, ty: t.ty, r: cur ? union(cur.r, r) : r });
|
|
1048
1057
|
}
|
|
@@ -1051,10 +1060,10 @@ var PaintStrokeSession = (_class6 = class {
|
|
|
1051
1060
|
const src = _nullishCoalesce(_optionalChain([this, 'access', _13 => _13.base, 'access', _14 => _14.tiles, 'access', _15 => _15.get, 'call', _16 => _16(key), 'optionalAccess', _17 => _17.data]), () => ( defaultTile(this.base)));
|
|
1052
1061
|
const prev = this.touched.has(key) ? _optionalChain([this, 'access', _18 => _18.live, 'access', _19 => _19.get, 'call', _20 => _20(key), 'optionalAccess', _21 => _21.data]) : void 0;
|
|
1053
1062
|
this.touched.add(key);
|
|
1054
|
-
const data =
|
|
1063
|
+
const data = _chunkHUFQD4CBcjs.applyStrokeToTile.call(void 0, this.dry.coverage, src, ch, tx, ty, this.apply, prev ? { into: prev, region: r } : {});
|
|
1055
1064
|
this.live.set(key, { data, uniform: null });
|
|
1056
1065
|
}
|
|
1057
|
-
this.host.update(this.layerId, new (0,
|
|
1066
|
+
this.host.update(this.layerId, new (0, _chunkSZ6KMZNMcjs.TiledSurface)(ch, new Map(this.live), this.base.defaultValue), rects);
|
|
1058
1067
|
}
|
|
1059
1068
|
/** Ends the stroke (one undo step) and returns what changed. */
|
|
1060
1069
|
end() {
|
|
@@ -1071,19 +1080,19 @@ var PaintStrokeSession = (_class6 = class {
|
|
|
1071
1080
|
const tiles = new Map(this.base.tiles);
|
|
1072
1081
|
let changed = false;
|
|
1073
1082
|
for (const key of this.touched) {
|
|
1074
|
-
const tile =
|
|
1083
|
+
const tile = _chunkSZ6KMZNMcjs.finishTile.call(void 0, this.live.get(key).data, ch, this.base.defaultValue);
|
|
1075
1084
|
const prev = this.base.tiles.get(key);
|
|
1076
1085
|
if (tile) tiles.set(key, tile);
|
|
1077
1086
|
else tiles.delete(key);
|
|
1078
1087
|
if (!sameTile(prev, tile)) changed = true;
|
|
1079
1088
|
}
|
|
1080
|
-
const surface = changed ? new (0,
|
|
1089
|
+
const surface = changed ? new (0, _chunkSZ6KMZNMcjs.TiledSurface)(ch, tiles, this.base.defaultValue) : null;
|
|
1081
1090
|
const dabs = this.dry ? this.dry.dabCount : this.mixers.reduce((n, m) => n + m.dabCount, 0);
|
|
1082
1091
|
this.result = { layerId: this.layerId, bounds: changed ? this.bounds : null, dabs, strokeId: null };
|
|
1083
1092
|
if (this.mixers.length) {
|
|
1084
1093
|
const brush = this.init.brush;
|
|
1085
1094
|
let load = this.mixers[0].load;
|
|
1086
|
-
if (brush.mixer.cleanEachStroke) load =
|
|
1095
|
+
if (brush.mixer.cleanEachStroke) load = _chunkHUFQD4CBcjs.cleanMixer.call(void 0, load);
|
|
1087
1096
|
this.result.mixerLoad = load;
|
|
1088
1097
|
}
|
|
1089
1098
|
this.host.commit(this, surface, false);
|
|
@@ -1098,7 +1107,7 @@ var PaintStrokeSession = (_class6 = class {
|
|
|
1098
1107
|
}, _class6);
|
|
1099
1108
|
function mixerLoadForStroke(brush, current, color) {
|
|
1100
1109
|
if (!brush.loadsColor) return { reservoir: null, amount: 0, pickup: brush.mixer.cleanEachStroke ? null : current.pickup };
|
|
1101
|
-
if (brush.mixer.loadEachStroke || !current.reservoir) return
|
|
1110
|
+
if (brush.mixer.loadEachStroke || !current.reservoir) return _chunkHUFQD4CBcjs.loadMixer.call(void 0, current, color);
|
|
1102
1111
|
return current;
|
|
1103
1112
|
}
|
|
1104
1113
|
|
|
@@ -1265,7 +1274,7 @@ var PROFILE = {
|
|
|
1265
1274
|
}
|
|
1266
1275
|
};
|
|
1267
1276
|
function createPaintCompositor() {
|
|
1268
|
-
return new (0,
|
|
1277
|
+
return new (0, _chunkT3QZ6S47cjs.RasterCompositor)(PROFILE);
|
|
1269
1278
|
}
|
|
1270
1279
|
function downsampleRgba(data, width, height, tw, th) {
|
|
1271
1280
|
tw = Math.max(1, Math.round(tw));
|
|
@@ -1336,11 +1345,11 @@ function header(state, options) {
|
|
|
1336
1345
|
return out;
|
|
1337
1346
|
}
|
|
1338
1347
|
function serializePaintDocument(state, options = {}) {
|
|
1339
|
-
const { layers, assets } =
|
|
1348
|
+
const { layers, assets } = _chunkFRD3FUXIcjs.serializeLayers.call(void 0, state.layers);
|
|
1340
1349
|
return { ...header(state, options), layers, assets };
|
|
1341
1350
|
}
|
|
1342
1351
|
async function serializePaintDocumentExternal(state, store, options = {}) {
|
|
1343
|
-
const { layers, assets } = await
|
|
1352
|
+
const { layers, assets } = await _chunkFRD3FUXIcjs.serializeLayersExternal.call(void 0, state.layers, store);
|
|
1344
1353
|
return { ...header(state, options), layers, assets };
|
|
1345
1354
|
}
|
|
1346
1355
|
function paintLayersOnly(layers, problems) {
|
|
@@ -1377,16 +1386,16 @@ function deserializePaintDocument(raw) {
|
|
|
1377
1386
|
const canvas = normalizeCanvas({ width: r.width, height: r.height, dpi: _nullishCoalesce(r.dpi, () => ( void 0)) });
|
|
1378
1387
|
const paper = normalizePaper(_nullishCoalesce(r.paper, () => ( {})));
|
|
1379
1388
|
const assets = r.assets && typeof r.assets === "object" ? r.assets : {};
|
|
1380
|
-
const layers = paintLayersOnly(
|
|
1389
|
+
const layers = paintLayersOnly(_chunkFRD3FUXIcjs.deserializeLayers.call(void 0, r.layers, { assets, problems }), problems);
|
|
1381
1390
|
const wanted = typeof r.activeLayerId === "string" ? r.activeLayerId : null;
|
|
1382
|
-
const activeLayerId = wanted &&
|
|
1391
|
+
const activeLayerId = wanted && _chunkT3QZ6S47cjs.findLayer.call(void 0, layers, wanted) ? wanted : _nullishCoalesce(_optionalChain([_chunkT3QZ6S47cjs.flattenLayers.call(void 0, layers), 'access', _25 => _25.filter, 'call', _26 => _26((l) => l.type === "pixel"), 'access', _27 => _27.pop, 'call', _28 => _28(), 'optionalAccess', _29 => _29.id]), () => ( null));
|
|
1383
1392
|
return { state: { canvas, paper, layers, activeLayerId, strokes: readStrokes(r.strokes, problems) }, extensions: documentExtensions(r), guides: r.guides, swatches: r.swatches, problems };
|
|
1384
1393
|
}
|
|
1385
1394
|
async function deserializePaintDocumentAsync(raw, store) {
|
|
1386
1395
|
if (!raw || typeof raw !== "object") throw new Error("Not a paint document: expected a JSON object.");
|
|
1387
1396
|
const r = raw;
|
|
1388
1397
|
const problems = [];
|
|
1389
|
-
const assets = await
|
|
1398
|
+
const assets = await _chunkFRD3FUXIcjs.resolveExternalAssets.call(void 0, _nullishCoalesce(r.assets, () => ( {})), store, problems);
|
|
1390
1399
|
const loaded = deserializePaintDocument({ ...r, assets });
|
|
1391
1400
|
return { ...loaded, problems: [...problems, ...loaded.problems] };
|
|
1392
1401
|
}
|
|
@@ -1565,7 +1574,7 @@ function paintTestStroke(surface, brush, paper, color, width, height) {
|
|
|
1565
1574
|
colorHex: color,
|
|
1566
1575
|
affineCopies: [],
|
|
1567
1576
|
copies: [IDENTITY_COPY],
|
|
1568
|
-
mixerLoad: brush.engine === "mixer" ? mixerLoadForStroke(brush,
|
|
1577
|
+
mixerLoad: brush.engine === "mixer" ? mixerLoadForStroke(brush, _chunkHUFQD4CBcjs.EMPTY_MIXER_LOAD, [r / 255, g / 255, b / 255]) : _chunkHUFQD4CBcjs.EMPTY_MIXER_LOAD
|
|
1569
1578
|
}
|
|
1570
1579
|
);
|
|
1571
1580
|
session.push(thumbnailStroke(width, height));
|
|
@@ -1578,13 +1587,13 @@ function renderBrushThumbnail(brush, options) {
|
|
|
1578
1587
|
const maxSize = height * 0.42;
|
|
1579
1588
|
const b = brush.tip.size > maxSize ? normalizePaintBrush({ tip: { ...brush.tip, size: maxSize } }, brush) : brush;
|
|
1580
1589
|
const rgba = [...hexToRgb8(options.color), 255];
|
|
1581
|
-
let surface =
|
|
1590
|
+
let surface = _chunkSZ6KMZNMcjs.emptySurface.call(void 0, 4);
|
|
1582
1591
|
if (b.engine === "eraser") {
|
|
1583
|
-
surface =
|
|
1592
|
+
surface = _chunkSZ6KMZNMcjs.fillRect.call(void 0, surface, { x: 0, y: 0, width, height }, rgba);
|
|
1584
1593
|
} else if (b.engine === "mixer" && !b.loadsColor) {
|
|
1585
1594
|
const half = Math.ceil(height / 2);
|
|
1586
|
-
surface =
|
|
1587
|
-
surface =
|
|
1595
|
+
surface = _chunkSZ6KMZNMcjs.fillRect.call(void 0, surface, { x: 0, y: 0, width, height: half }, rgba);
|
|
1596
|
+
surface = _chunkSZ6KMZNMcjs.fillRect.call(void 0, surface, { x: 0, y: half, width, height: height - half }, [232, 196, 64, 255]);
|
|
1588
1597
|
}
|
|
1589
1598
|
surface = paintTestStroke(surface, b, options.paper, options.color, width, height);
|
|
1590
1599
|
const layer = { type: "pixel", id: "thumbnail", name: "thumbnail", visible: true, opacity: 1, blend: "normal", surface, offset: { x: 0, y: 0 } };
|
|
@@ -1912,7 +1921,7 @@ var PAD_KNIFE = normalizePaintBrush({
|
|
|
1912
1921
|
var MixingPad = (_class8 = class {constructor() { _class8.prototype.__init29.call(this);_class8.prototype.__init30.call(this);_class8.prototype.__init31.call(this);_class8.prototype.__init32.call(this); }
|
|
1913
1922
|
__init29() {this.width = MIXING_PAD_WIDTH}
|
|
1914
1923
|
__init30() {this.height = MIXING_PAD_HEIGHT}
|
|
1915
|
-
__init31() {this.surface =
|
|
1924
|
+
__init31() {this.surface = _chunkSZ6KMZNMcjs.emptySurface.call(void 0, 4)}
|
|
1916
1925
|
/** Increments on every change (for redrawing). */
|
|
1917
1926
|
__init32() {this.version = 0}
|
|
1918
1927
|
/** Paints (`paint`, with `color`) or smears (`knife`) through `points` in pad pixels. */
|
|
@@ -1944,7 +1953,7 @@ var MixingPad = (_class8 = class {constructor() { _class8.prototype.__init29.cal
|
|
|
1944
1953
|
colorHex: options.color,
|
|
1945
1954
|
affineCopies: [],
|
|
1946
1955
|
copies: [IDENTITY_COPY],
|
|
1947
|
-
mixerLoad: mixerLoadForStroke(brush,
|
|
1956
|
+
mixerLoad: mixerLoadForStroke(brush, _chunkHUFQD4CBcjs.EMPTY_MIXER_LOAD, [r / 255, g / 255, b / 255])
|
|
1948
1957
|
}
|
|
1949
1958
|
);
|
|
1950
1959
|
session.push(points);
|
|
@@ -1963,7 +1972,7 @@ var MixingPad = (_class8 = class {constructor() { _class8.prototype.__init29.cal
|
|
|
1963
1972
|
const y0 = Math.max(0, Math.floor(y) - r);
|
|
1964
1973
|
const x1 = Math.min(this.width, Math.floor(x) + r + 1);
|
|
1965
1974
|
const y1 = Math.min(this.height, Math.floor(y) + r + 1);
|
|
1966
|
-
const px =
|
|
1975
|
+
const px = _chunkSZ6KMZNMcjs.readRegion.call(void 0, this.surface, { x: x0, y: y0, width: x1 - x0, height: y1 - y0 });
|
|
1967
1976
|
let R = 0;
|
|
1968
1977
|
let G = 0;
|
|
1969
1978
|
let B = 0;
|
|
@@ -1980,12 +1989,12 @@ var MixingPad = (_class8 = class {constructor() { _class8.prototype.__init29.cal
|
|
|
1980
1989
|
return `#${hex(R)}${hex(G)}${hex(B)}`;
|
|
1981
1990
|
}
|
|
1982
1991
|
clear() {
|
|
1983
|
-
this.surface =
|
|
1992
|
+
this.surface = _chunkSZ6KMZNMcjs.emptySurface.call(void 0, 4);
|
|
1984
1993
|
this.version++;
|
|
1985
1994
|
}
|
|
1986
1995
|
/** The pad over white, `width × height` RGBA. */
|
|
1987
1996
|
pixels() {
|
|
1988
|
-
const px =
|
|
1997
|
+
const px = _chunkSZ6KMZNMcjs.readRegion.call(void 0, this.surface, { x: 0, y: 0, width: this.width, height: this.height });
|
|
1989
1998
|
for (let i = 0; i < px.length; i += 4) {
|
|
1990
1999
|
const a = px[i + 3] / 255;
|
|
1991
2000
|
px[i] = Math.round(px[i] * a + 255 * (1 - a));
|
|
@@ -2034,7 +2043,7 @@ var PaintEditorController = (_class9 = class {
|
|
|
2034
2043
|
|
|
2035
2044
|
|
|
2036
2045
|
__init36() {this.secondaryColor = "#ffffff"}
|
|
2037
|
-
__init37() {this.mixerLoad =
|
|
2046
|
+
__init37() {this.mixerLoad = _chunkHUFQD4CBcjs.EMPTY_MIXER_LOAD}
|
|
2038
2047
|
__init38() {this.view = { ...DEFAULT_VIEW, pan: { ...DEFAULT_VIEW.pan } }}
|
|
2039
2048
|
|
|
2040
2049
|
|
|
@@ -2204,7 +2213,7 @@ var PaintEditorController = (_class9 = class {
|
|
|
2204
2213
|
}
|
|
2205
2214
|
// --- Layers --------------------------------------------------------------------
|
|
2206
2215
|
getLayer(id) {
|
|
2207
|
-
return _optionalChain([
|
|
2216
|
+
return _optionalChain([_chunkT3QZ6S47cjs.findLayer.call(void 0, this.doc.layers, id), 'optionalAccess', _35 => _35.layer]);
|
|
2208
2217
|
}
|
|
2209
2218
|
/** The active pixel layer (or `undefined`). */
|
|
2210
2219
|
getActiveLayer() {
|
|
@@ -2223,12 +2232,12 @@ var PaintEditorController = (_class9 = class {
|
|
|
2223
2232
|
walk(this.doc.layers, null, 0);
|
|
2224
2233
|
return out;
|
|
2225
2234
|
}
|
|
2226
|
-
describeLayer(l, parentId = _nullishCoalesce(_optionalChain([
|
|
2235
|
+
describeLayer(l, parentId = _nullishCoalesce(_optionalChain([_chunkT3QZ6S47cjs.findLayer.call(void 0, this.doc.layers, l.id), 'optionalAccess', _36 => _36.parent, 'optionalAccess', _37 => _37.id]), () => ( null)), depth = _nullishCoalesce(_optionalChain([_chunkT3QZ6S47cjs.findLayer.call(void 0, this.doc.layers, l.id), 'optionalAccess', _38 => _38.path, 'access', _39 => _39.length]), () => ( 0))) {
|
|
2227
2236
|
let bounds = null;
|
|
2228
2237
|
if (l.type === "pixel") {
|
|
2229
|
-
const b =
|
|
2238
|
+
const b = _chunkSZ6KMZNMcjs.contentBounds.call(void 0, l.surface);
|
|
2230
2239
|
bounds = b ? { ...b, x: b.x + l.offset.x, y: b.y + l.offset.y } : null;
|
|
2231
|
-
} else for (const c of
|
|
2240
|
+
} else for (const c of _chunkT3QZ6S47cjs.flattenLayers.call(void 0, l.children)) if (c.type === "pixel") bounds = unionRect(bounds, this.describeLayer(c, l.id, depth + 1).bounds);
|
|
2232
2241
|
return {
|
|
2233
2242
|
id: l.id,
|
|
2234
2243
|
name: l.name,
|
|
@@ -2255,7 +2264,7 @@ var PaintEditorController = (_class9 = class {
|
|
|
2255
2264
|
if (!id) throw new PaintEditorError(`There is no active layer to ${what}; add one with add_layer.`);
|
|
2256
2265
|
const l = this.requireLayer(id);
|
|
2257
2266
|
if (!isPixelLayer(l)) throw new PaintEditorError(`Layer "${l.name}" is a group; ${what} a pixel layer inside it.`);
|
|
2258
|
-
if (
|
|
2267
|
+
if (_chunkT3QZ6S47cjs.isLayerLocked.call(void 0, l, "pixels")) throw new PaintEditorError(`Layer "${l.name}" has its pixels locked; unlock it (update_layer locks) before you ${what} it.`);
|
|
2259
2268
|
if (!l.visible) throw new PaintEditorError(`Layer "${l.name}" is hidden; show it (update_layer visible true) before you ${what} it.`);
|
|
2260
2269
|
return l;
|
|
2261
2270
|
}
|
|
@@ -2268,7 +2277,7 @@ var PaintEditorController = (_class9 = class {
|
|
|
2268
2277
|
/** Adds an empty pixel layer or group above `aboveId` (default: the active layer) and makes it active. */
|
|
2269
2278
|
addLayer(options = {}) {
|
|
2270
2279
|
this.requireIdle("adding a layer");
|
|
2271
|
-
const count =
|
|
2280
|
+
const count = _chunkT3QZ6S47cjs.flattenLayers.call(void 0, this.doc.layers).length;
|
|
2272
2281
|
const type = _nullishCoalesce(options.type, () => ( "pixel"));
|
|
2273
2282
|
const name = _optionalChain([options, 'access', _40 => _40.name, 'optionalAccess', _41 => _41.trim, 'call', _42 => _42()]) || (type === "group" ? `Group ${count + 1}` : `Layer ${count + 1}`);
|
|
2274
2283
|
const layer = type === "group" ? { type: "group", id: newPaintLayerId(), name, visible: true, opacity: 1, blend: "pass-through", children: [] } : createPaintLayer(name);
|
|
@@ -2280,21 +2289,21 @@ var PaintEditorController = (_class9 = class {
|
|
|
2280
2289
|
if (g.type !== "group") throw new PaintEditorError(`Layer "${g.name}" is not a group; pass a group id as parentId.`);
|
|
2281
2290
|
parentId = g.id;
|
|
2282
2291
|
} else if (above) {
|
|
2283
|
-
const loc =
|
|
2292
|
+
const loc = _chunkT3QZ6S47cjs.findLayer.call(void 0, this.doc.layers, above);
|
|
2284
2293
|
if (!loc) throw new PaintEditorError(`Unknown layer "${above}". Call list_layers for the ids.`);
|
|
2285
2294
|
parentId = _nullishCoalesce(_optionalChain([loc, 'access', _43 => _43.parent, 'optionalAccess', _44 => _44.id]), () => ( null));
|
|
2286
2295
|
index = loc.index + 1;
|
|
2287
2296
|
}
|
|
2288
|
-
const layers =
|
|
2297
|
+
const layers = _chunkT3QZ6S47cjs.insertLayer.call(void 0, this.doc.layers, layer, parentId, index);
|
|
2289
2298
|
this.commit(type === "group" ? "Add group" : "Add layer", { ...this.doc, layers, activeLayerId: layer.id });
|
|
2290
2299
|
return this.describeLayer(layer);
|
|
2291
2300
|
}
|
|
2292
2301
|
updateLayer(id, update) {
|
|
2293
2302
|
this.requireIdle("changing a layer");
|
|
2294
2303
|
const l = this.requireLayer(id);
|
|
2295
|
-
if (
|
|
2304
|
+
if (_chunkT3QZ6S47cjs.isLayerLocked.call(void 0, l, "all") && Object.keys(update).some((k) => k !== "locks")) throw new PaintEditorError(`Layer "${l.name}" is fully locked; unlock it first (locks {all: false}).`);
|
|
2296
2305
|
if (update.opacity !== void 0 && !(update.opacity >= 0 && update.opacity <= 1)) throw new PaintEditorError(`opacity ${update.opacity} is out of range; use 0..1.`);
|
|
2297
|
-
if (update.blend !== void 0 && !
|
|
2306
|
+
if (update.blend !== void 0 && !_chunkSZ6KMZNMcjs.isBlendMode.call(void 0, update.blend) && !(l.type === "group" && update.blend === "pass-through")) {
|
|
2298
2307
|
throw new PaintEditorError(`Unknown blend mode "${update.blend}". Call get_canvas_info for the blend modes.`);
|
|
2299
2308
|
}
|
|
2300
2309
|
if (update.name !== void 0 && !update.name.trim()) throw new PaintEditorError("name is empty; give the layer a name.");
|
|
@@ -2308,66 +2317,66 @@ var PaintEditorController = (_class9 = class {
|
|
|
2308
2317
|
const locks = { ..._nullishCoalesce(l.locks, () => ( {})), ...update.locks };
|
|
2309
2318
|
next.locks = Object.values(locks).some(Boolean) ? locks : void 0;
|
|
2310
2319
|
}
|
|
2311
|
-
this.commit("Layer properties", { ...this.doc, layers:
|
|
2320
|
+
this.commit("Layer properties", { ...this.doc, layers: _chunkT3QZ6S47cjs.mapLayer.call(void 0, this.doc.layers, id, () => next) });
|
|
2312
2321
|
return this.describeLayer(next);
|
|
2313
2322
|
}
|
|
2314
2323
|
removeLayer(id) {
|
|
2315
2324
|
this.requireIdle("removing a layer");
|
|
2316
2325
|
const l = this.requireLayer(id);
|
|
2317
|
-
if (
|
|
2318
|
-
const layers =
|
|
2326
|
+
if (_chunkT3QZ6S47cjs.isLayerLocked.call(void 0, l, "all")) throw new PaintEditorError(`Layer "${l.name}" is fully locked; unlock it before removing it.`);
|
|
2327
|
+
const layers = _chunkT3QZ6S47cjs.mapLayer.call(void 0, this.doc.layers, id, () => null);
|
|
2319
2328
|
let active = this.doc.activeLayerId;
|
|
2320
|
-
if (active && !
|
|
2329
|
+
if (active && !_chunkT3QZ6S47cjs.findLayer.call(void 0, layers, active)) active = _nullishCoalesce(_optionalChain([_chunkT3QZ6S47cjs.flattenLayers.call(void 0, layers), 'access', _45 => _45.filter, 'call', _46 => _46((x) => x.type === "pixel"), 'access', _47 => _47.pop, 'call', _48 => _48(), 'optionalAccess', _49 => _49.id]), () => ( null));
|
|
2321
2330
|
this.commit("Remove layer", { ...this.doc, layers, activeLayerId: active });
|
|
2322
2331
|
return { removed: id, activeLayerId: active };
|
|
2323
2332
|
}
|
|
2324
2333
|
duplicateLayer(id) {
|
|
2325
2334
|
this.requireIdle("duplicating a layer");
|
|
2326
|
-
const loc =
|
|
2335
|
+
const loc = _chunkT3QZ6S47cjs.findLayer.call(void 0, this.doc.layers, id);
|
|
2327
2336
|
if (!loc) throw new PaintEditorError(`Unknown layer "${id}". Call list_layers for the ids.`);
|
|
2328
2337
|
const copy = (l) => l.type === "group" ? { ...l, id: newPaintLayerId(), children: l.children.map(copy) } : { ...l, id: newPaintLayerId() };
|
|
2329
2338
|
const dup = { ...copy(loc.layer), name: `${loc.layer.name} copy` };
|
|
2330
|
-
const layers =
|
|
2339
|
+
const layers = _chunkT3QZ6S47cjs.insertLayer.call(void 0, this.doc.layers, dup, _nullishCoalesce(_optionalChain([loc, 'access', _50 => _50.parent, 'optionalAccess', _51 => _51.id]), () => ( null)), loc.index + 1);
|
|
2331
2340
|
this.commit("Duplicate layer", { ...this.doc, layers, activeLayerId: dup.id });
|
|
2332
2341
|
return this.describeLayer(dup);
|
|
2333
2342
|
}
|
|
2334
2343
|
/** Moves a layer to `index` (0 = bottom) within `parentId` (default its own parent; `null` = top level). */
|
|
2335
2344
|
moveLayer(id, index, parentId) {
|
|
2336
2345
|
this.requireIdle("moving a layer");
|
|
2337
|
-
const loc =
|
|
2346
|
+
const loc = _chunkT3QZ6S47cjs.findLayer.call(void 0, this.doc.layers, id);
|
|
2338
2347
|
if (!loc) throw new PaintEditorError(`Unknown layer "${id}". Call list_layers for the ids.`);
|
|
2339
2348
|
const target = parentId === void 0 ? _nullishCoalesce(_optionalChain([loc, 'access', _52 => _52.parent, 'optionalAccess', _53 => _53.id]), () => ( null)) : parentId;
|
|
2340
2349
|
if (target) {
|
|
2341
2350
|
const g = this.requireLayer(target);
|
|
2342
2351
|
if (g.type !== "group") throw new PaintEditorError(`Layer "${g.name}" is not a group; pass a group id as parentId.`);
|
|
2343
|
-
if (target === id || loc.layer.type === "group" &&
|
|
2352
|
+
if (target === id || loc.layer.type === "group" && _chunkT3QZ6S47cjs.findLayer.call(void 0, loc.layer.children, target)) throw new PaintEditorError("A group cannot move into itself.");
|
|
2344
2353
|
}
|
|
2345
|
-
const without =
|
|
2346
|
-
const siblings = target ?
|
|
2354
|
+
const without = _chunkT3QZ6S47cjs.mapLayer.call(void 0, this.doc.layers, id, () => null);
|
|
2355
|
+
const siblings = target ? _chunkT3QZ6S47cjs.findLayer.call(void 0, without, target).layer.children : without;
|
|
2347
2356
|
if (!Number.isInteger(index) || index < 0 || index > siblings.length) throw new PaintEditorError(`index ${index} is out of range; use 0..${siblings.length} (0 is the bottom).`);
|
|
2348
|
-
const layers =
|
|
2357
|
+
const layers = _chunkT3QZ6S47cjs.insertLayer.call(void 0, without, loc.layer, target, index);
|
|
2349
2358
|
this.commit("Move layer", { ...this.doc, layers });
|
|
2350
2359
|
return this.describeLayer(loc.layer);
|
|
2351
2360
|
}
|
|
2352
2361
|
/** Merges a pixel layer into the pixel layer below it (keeping the lower one's settings). */
|
|
2353
2362
|
mergeDown(id) {
|
|
2354
2363
|
this.requireIdle("merging");
|
|
2355
|
-
const loc =
|
|
2364
|
+
const loc = _chunkT3QZ6S47cjs.findLayer.call(void 0, this.doc.layers, id);
|
|
2356
2365
|
if (!loc) throw new PaintEditorError(`Unknown layer "${id}". Call list_layers for the ids.`);
|
|
2357
2366
|
const siblings = loc.parent ? loc.parent.children : this.doc.layers;
|
|
2358
2367
|
const below = siblings[loc.index - 1];
|
|
2359
2368
|
const upper = loc.layer;
|
|
2360
2369
|
if (!isPixelLayer(upper) || !isPixelLayer(below)) throw new PaintEditorError("Merge down needs a pixel layer directly above another pixel layer in the same group.");
|
|
2361
|
-
if (
|
|
2370
|
+
if (_chunkT3QZ6S47cjs.isLayerLocked.call(void 0, below, "pixels")) throw new PaintEditorError(`Layer "${below.name}" has its pixels locked; unlock it to merge into it.`);
|
|
2362
2371
|
const rect = unionRect(this.describeLayer(below).bounds, this.describeLayer(upper).bounds);
|
|
2363
|
-
let surface =
|
|
2372
|
+
let surface = _chunkSZ6KMZNMcjs.emptySurface.call(void 0, 4);
|
|
2364
2373
|
if (rect) {
|
|
2365
2374
|
const base = { ...below, opacity: 1, blend: "normal", visible: true, clipped: void 0, mask: void 0 };
|
|
2366
2375
|
const px = createPaintCompositor().composite([base, upper.visible ? upper : { ...upper, opacity: 0 }], rect, this.sources());
|
|
2367
|
-
surface =
|
|
2376
|
+
surface = _chunkSZ6KMZNMcjs.surfaceFromPixels.call(void 0, { width: rect.width, height: rect.height, data: px }, 4, rect.x, rect.y);
|
|
2368
2377
|
}
|
|
2369
2378
|
const merged = { ...below, surface, offset: { x: 0, y: 0 } };
|
|
2370
|
-
const layers =
|
|
2379
|
+
const layers = _chunkT3QZ6S47cjs.mapLayer.call(void 0, _chunkT3QZ6S47cjs.mapLayer.call(void 0, this.doc.layers, upper.id, () => null), below.id, () => merged);
|
|
2371
2380
|
this.commit("Merge down", { ...this.doc, layers, activeLayerId: below.id });
|
|
2372
2381
|
return this.describeLayer(merged);
|
|
2373
2382
|
}
|
|
@@ -2376,7 +2385,7 @@ var PaintEditorController = (_class9 = class {
|
|
|
2376
2385
|
this.requireIdle("clearing");
|
|
2377
2386
|
const l = this.paintTarget(layerId, "clear");
|
|
2378
2387
|
const bounds = this.describeLayer(l).bounds;
|
|
2379
|
-
this.commit("Clear layer", { ...this.doc, layers:
|
|
2388
|
+
this.commit("Clear layer", { ...this.doc, layers: _chunkT3QZ6S47cjs.mapLayer.call(void 0, this.doc.layers, l.id, () => ({ ...l, surface: _chunkSZ6KMZNMcjs.emptySurface.call(void 0, 4) })) });
|
|
2380
2389
|
return { layerId: l.id, bounds };
|
|
2381
2390
|
}
|
|
2382
2391
|
/**
|
|
@@ -2393,14 +2402,14 @@ var PaintEditorController = (_class9 = class {
|
|
|
2393
2402
|
if (!(grainAmount >= 0 && grainAmount <= 1)) throw new PaintEditorError(`grain ${grainAmount} is out of range; use 0..1.`);
|
|
2394
2403
|
const pressure = _nullishCoalesce(options.pressure, () => ( 0.5));
|
|
2395
2404
|
const blend = _nullishCoalesce(options.blend, () => ( "normal"));
|
|
2396
|
-
if (!
|
|
2405
|
+
if (!_chunkSZ6KMZNMcjs.isBlendMode.call(void 0, blend)) throw new PaintEditorError(`Unknown blend mode "${blend}".`);
|
|
2397
2406
|
const { width, height } = this.doc.canvas;
|
|
2398
2407
|
const rect = { x: 0, y: 0, width, height };
|
|
2399
|
-
const coverage = new (0,
|
|
2408
|
+
const coverage = new (0, _chunkHUFQD4CBcjs.CoverageMap)();
|
|
2400
2409
|
const depth = grainAmount * this.doc.paper.depth;
|
|
2401
2410
|
const grain = depth > 0 ? paperGrain(this.doc.paper) : null;
|
|
2402
|
-
for (const { tx, ty } of
|
|
2403
|
-
const r = { x: tx *
|
|
2411
|
+
for (const { tx, ty } of _chunkSZ6KMZNMcjs.tilesInRect.call(void 0, rect)) {
|
|
2412
|
+
const r = { x: tx * _chunkSZ6KMZNMcjs.TILE, y: ty * _chunkSZ6KMZNMcjs.TILE, width: Math.min(_chunkSZ6KMZNMcjs.TILE, width - tx * _chunkSZ6KMZNMcjs.TILE), height: Math.min(_chunkSZ6KMZNMcjs.TILE, height - ty * _chunkSZ6KMZNMcjs.TILE) };
|
|
2404
2413
|
const vals = new Float32Array(r.width * r.height);
|
|
2405
2414
|
for (let y = 0, k = 0; y < r.height; y++) for (let x = 0; x < r.width; x++, k++) vals[k] = grain ? grainCatch(grain.at(r.x + x + 0.5, r.y + y + 0.5), depth, pressure) : 1;
|
|
2406
2415
|
coverage.accumulate(r, vals, 1);
|
|
@@ -2411,25 +2420,25 @@ var PaintEditorController = (_class9 = class {
|
|
|
2411
2420
|
background: rgbaOf(this.doc.paper.color),
|
|
2412
2421
|
opacity,
|
|
2413
2422
|
blend,
|
|
2414
|
-
lockTransparency:
|
|
2423
|
+
lockTransparency: _chunkT3QZ6S47cjs.isLayerLocked.call(void 0, l, "transparency"),
|
|
2415
2424
|
selection: null,
|
|
2416
2425
|
offset: l.offset
|
|
2417
2426
|
};
|
|
2418
2427
|
const surface = this.applyCoverage(l, coverage, rect, apply);
|
|
2419
|
-
this.commit("Fill layer", { ...this.doc, layers:
|
|
2428
|
+
this.commit("Fill layer", { ...this.doc, layers: _chunkT3QZ6S47cjs.mapLayer.call(void 0, this.doc.layers, l.id, () => ({ ...l, surface })) });
|
|
2420
2429
|
return { layerId: l.id, bounds: rect };
|
|
2421
2430
|
}
|
|
2422
2431
|
applyCoverage(l, coverage, rect, apply) {
|
|
2423
2432
|
const base = l.surface;
|
|
2424
2433
|
const tiles = new Map(base.tiles);
|
|
2425
|
-
for (const { tx, ty } of
|
|
2426
|
-
const key =
|
|
2427
|
-
const src = _nullishCoalesce(_optionalChain([base, 'access', _54 => _54.tiles, 'access', _55 => _55.get, 'call', _56 => _56(key), 'optionalAccess', _57 => _57.data]), () => ( new Uint8ClampedArray(
|
|
2428
|
-
const tile =
|
|
2434
|
+
for (const { tx, ty } of _chunkSZ6KMZNMcjs.tilesInRect.call(void 0, { x: rect.x - l.offset.x, y: rect.y - l.offset.y, width: rect.width, height: rect.height })) {
|
|
2435
|
+
const key = _chunkSZ6KMZNMcjs.tileKey.call(void 0, tx, ty);
|
|
2436
|
+
const src = _nullishCoalesce(_optionalChain([base, 'access', _54 => _54.tiles, 'access', _55 => _55.get, 'call', _56 => _56(key), 'optionalAccess', _57 => _57.data]), () => ( new Uint8ClampedArray(_chunkSZ6KMZNMcjs.TILE * _chunkSZ6KMZNMcjs.TILE * 4)));
|
|
2437
|
+
const tile = _chunkSZ6KMZNMcjs.finishTile.call(void 0, _chunkHUFQD4CBcjs.applyStrokeToTile.call(void 0, coverage, src, 4, tx, ty, apply), 4, 0);
|
|
2429
2438
|
if (tile) tiles.set(key, tile);
|
|
2430
2439
|
else tiles.delete(key);
|
|
2431
2440
|
}
|
|
2432
|
-
return new (0,
|
|
2441
|
+
return new (0, _chunkSZ6KMZNMcjs.TiledSurface)(4, tiles, 0);
|
|
2433
2442
|
}
|
|
2434
2443
|
// --- Brushes -------------------------------------------------------------------
|
|
2435
2444
|
findBrush(id) {
|
|
@@ -2549,7 +2558,7 @@ var PaintEditorController = (_class9 = class {
|
|
|
2549
2558
|
if (options.layerId !== void 0) {
|
|
2550
2559
|
const l = this.requireLayer(options.layerId);
|
|
2551
2560
|
if (!isPixelLayer(l)) throw new PaintEditorError(`Layer "${l.name}" is a group; pick from a pixel layer or the composite.`);
|
|
2552
|
-
const [r, g, b, a] =
|
|
2561
|
+
const [r, g, b, a] = _chunkSZ6KMZNMcjs.readPixel.call(void 0, l.surface, px - l.offset.x, py - l.offset.y);
|
|
2553
2562
|
return { color: rgbToHex(r, g, b), alpha: Math.round(a / 255 * 1e3) / 1e3 };
|
|
2554
2563
|
}
|
|
2555
2564
|
const d = this.exportCompositor.composite(this.renderLayers({}), { x: px, y: py, width: 1, height: 1 }, this.sources());
|
|
@@ -2559,13 +2568,13 @@ var PaintEditorController = (_class9 = class {
|
|
|
2559
2568
|
/** Fills the Mixer Brush reservoir with a colour (default the editor colour). */
|
|
2560
2569
|
loadMixerBrush(color) {
|
|
2561
2570
|
const [r, g, b] = hexToRgb8(color === void 0 ? this.color : parseColor(color));
|
|
2562
|
-
this.mixerLoad =
|
|
2571
|
+
this.mixerLoad = _chunkHUFQD4CBcjs.loadMixer.call(void 0, this.mixerLoad, [r / 255, g / 255, b / 255]);
|
|
2563
2572
|
this.emit([]);
|
|
2564
2573
|
return this.mixerLoad;
|
|
2565
2574
|
}
|
|
2566
2575
|
/** Empties the pickup well (and with `emptyReservoir` the loaded paint too). */
|
|
2567
2576
|
cleanMixerBrush(emptyReservoir = false) {
|
|
2568
|
-
this.mixerLoad = emptyReservoir ?
|
|
2577
|
+
this.mixerLoad = emptyReservoir ? _chunkHUFQD4CBcjs.EMPTY_MIXER_LOAD : _chunkHUFQD4CBcjs.cleanMixer.call(void 0, this.mixerLoad);
|
|
2569
2578
|
this.emit([]);
|
|
2570
2579
|
return this.mixerLoad;
|
|
2571
2580
|
}
|
|
@@ -2599,11 +2608,11 @@ var PaintEditorController = (_class9 = class {
|
|
|
2599
2608
|
const layer = (() => {
|
|
2600
2609
|
const id = _nullishCoalesce(init.layerId, () => ( doc.activeLayerId));
|
|
2601
2610
|
if (!id) throw new PaintEditorError("There is no active layer to paint on; add one with add_layer.");
|
|
2602
|
-
const loc =
|
|
2611
|
+
const loc = _chunkT3QZ6S47cjs.findLayer.call(void 0, doc.layers, id);
|
|
2603
2612
|
if (!loc) throw new PaintEditorError(`Unknown layer "${id}". Call list_layers for the ids.`);
|
|
2604
2613
|
const l = loc.layer;
|
|
2605
2614
|
if (!isPixelLayer(l)) throw new PaintEditorError(`Layer "${l.name}" is a group; paint on a pixel layer inside it.`);
|
|
2606
|
-
if (
|
|
2615
|
+
if (_chunkT3QZ6S47cjs.isLayerLocked.call(void 0, l, "pixels")) throw new PaintEditorError(`Layer "${l.name}" has its pixels locked; unlock it (update_layer locks) to paint on it.`);
|
|
2607
2616
|
if (!l.visible) throw new PaintEditorError(`Layer "${l.name}" is hidden; show it (update_layer visible true) to paint on it.`);
|
|
2608
2617
|
return l;
|
|
2609
2618
|
})();
|
|
@@ -2620,7 +2629,7 @@ var PaintEditorController = (_class9 = class {
|
|
|
2620
2629
|
layerId: layer.id,
|
|
2621
2630
|
surface: layer.surface,
|
|
2622
2631
|
offset: layer.offset,
|
|
2623
|
-
lockTransparency:
|
|
2632
|
+
lockTransparency: _chunkT3QZ6S47cjs.isLayerLocked.call(void 0, layer, "transparency"),
|
|
2624
2633
|
brush,
|
|
2625
2634
|
color: rgba,
|
|
2626
2635
|
background: rgbaOf(doc.paper.color),
|
|
@@ -2631,7 +2640,7 @@ var PaintEditorController = (_class9 = class {
|
|
|
2631
2640
|
affineCopies: copies,
|
|
2632
2641
|
copies: [IDENTITY_AFFINE, ...copies].map(affineCopy),
|
|
2633
2642
|
inputFilter: snapper ? (p) => snapper.snap(p) : void 0,
|
|
2634
|
-
mixerLoad: brush.engine === "mixer" ? mixerLoadForStroke(brush, this.mixerLoad, [rgba[0] / 255, rgba[1] / 255, rgba[2] / 255]) :
|
|
2643
|
+
mixerLoad: brush.engine === "mixer" ? mixerLoadForStroke(brush, this.mixerLoad, [rgba[0] / 255, rgba[1] / 255, rgba[2] / 255]) : _chunkHUFQD4CBcjs.EMPTY_MIXER_LOAD
|
|
2635
2644
|
});
|
|
2636
2645
|
return session;
|
|
2637
2646
|
}
|
|
@@ -2672,7 +2681,7 @@ var PaintEditorController = (_class9 = class {
|
|
|
2672
2681
|
const stroke = this.record(s);
|
|
2673
2682
|
s.result.strokeId = stroke.id;
|
|
2674
2683
|
const l = this.getLayer(s.layerId);
|
|
2675
|
-
this.commit(`${brush.name} stroke`, { ...this.doc, layers:
|
|
2684
|
+
this.commit(`${brush.name} stroke`, { ...this.doc, layers: _chunkT3QZ6S47cjs.mapLayer.call(void 0, this.doc.layers, l.id, () => ({ ...l, surface })), strokes: [...this.doc.strokes, stroke] });
|
|
2676
2685
|
}
|
|
2677
2686
|
};
|
|
2678
2687
|
const session = this.sessionFor(this.doc, { snapToPerspective: true, ...init }, host);
|
|
@@ -2694,8 +2703,8 @@ var PaintEditorController = (_class9 = class {
|
|
|
2694
2703
|
if (cancelled || !surface) return;
|
|
2695
2704
|
const stroke = this.record(s);
|
|
2696
2705
|
s.result.strokeId = stroke.id;
|
|
2697
|
-
const l =
|
|
2698
|
-
out = { ...out, layers:
|
|
2706
|
+
const l = _chunkT3QZ6S47cjs.findLayer.call(void 0, out.layers, s.layerId).layer;
|
|
2707
|
+
out = { ...out, layers: _chunkT3QZ6S47cjs.mapLayer.call(void 0, out.layers, l.id, () => ({ ...l, surface })), strokes: [...out.strokes, stroke] };
|
|
2699
2708
|
}
|
|
2700
2709
|
};
|
|
2701
2710
|
const session = this.sessionFor(doc, init, host);
|
|
@@ -2713,6 +2722,7 @@ var PaintEditorController = (_class9 = class {
|
|
|
2713
2722
|
else this.emit([]);
|
|
2714
2723
|
return result;
|
|
2715
2724
|
}
|
|
2725
|
+
/** Checks stroke samples (finite x and y, pressure 0..1) and returns them; throws a sentence naming the bad point. */
|
|
2716
2726
|
checkPoints(points) {
|
|
2717
2727
|
if (!Array.isArray(points) || !points.length) throw new PaintEditorError("points is empty; give at least one {x, y} in document pixels.");
|
|
2718
2728
|
const out = [];
|
|
@@ -2766,7 +2776,7 @@ var PaintEditorController = (_class9 = class {
|
|
|
2766
2776
|
brush = normalizePaintBrush({ tip: { ...b.tip, size: b.tip.size * (v.brush.tip.size / s.brush.tip.size) } }, b);
|
|
2767
2777
|
}
|
|
2768
2778
|
const layerId = _nullishCoalesce(options.layerId, () => ( s.layerId));
|
|
2769
|
-
if (!
|
|
2779
|
+
if (!_chunkT3QZ6S47cjs.findLayer.call(void 0, doc.layers, layerId)) throw new PaintEditorError(`Stroke "${s.id}" was painted on layer "${layerId}", which no longer exists; pass layerId to replay it elsewhere.`);
|
|
2770
2780
|
const run = this.runStroke(doc, { layerId, color: _nullishCoalesce(options.color, () => ( s.color)), brush, seed: s.seed, copies: _nullishCoalesce(v.copies, () => ( [])) }, v.points);
|
|
2771
2781
|
doc = run.doc;
|
|
2772
2782
|
bounds = unionRect(bounds, run.result.bounds);
|
|
@@ -2786,7 +2796,7 @@ var PaintEditorController = (_class9 = class {
|
|
|
2786
2796
|
const live = this.live;
|
|
2787
2797
|
if (!live) return this.doc.layers;
|
|
2788
2798
|
if (_optionalChain([this, 'access', _63 => _63.liveLayers, 'optionalAccess', _64 => _64.key]) === live.surface) return this.liveLayers.layers;
|
|
2789
|
-
const layers =
|
|
2799
|
+
const layers = _chunkT3QZ6S47cjs.mapLayer.call(void 0, this.doc.layers, live.layerId, (l) => ({ ...l, surface: live.surface }));
|
|
2790
2800
|
this.liveLayers = { key: live.surface, layers };
|
|
2791
2801
|
return layers;
|
|
2792
2802
|
}
|
|
@@ -2890,7 +2900,7 @@ var PaintEditorController = (_class9 = class {
|
|
|
2890
2900
|
/** The canvas as PNG bytes (paper included by default; `scale` below 1 shrinks it). */
|
|
2891
2901
|
exportPng(options = {}) {
|
|
2892
2902
|
const img = this.scaled(options);
|
|
2893
|
-
return
|
|
2903
|
+
return _chunkT3QZ6S47cjs.encodePng.call(void 0, img.width, img.height, img.data);
|
|
2894
2904
|
}
|
|
2895
2905
|
scaled(options) {
|
|
2896
2906
|
const full = this.compositePixels(options);
|
|
@@ -2932,19 +2942,32 @@ var PaintEditorController = (_class9 = class {
|
|
|
2932
2942
|
opacity: 1,
|
|
2933
2943
|
blend: "normal",
|
|
2934
2944
|
locks: { all: true },
|
|
2935
|
-
surface:
|
|
2945
|
+
surface: _chunkSZ6KMZNMcjs.surfaceFromPixels.call(void 0, paperPixels, 4),
|
|
2936
2946
|
offset: { x: 0, y: 0 }
|
|
2937
2947
|
};
|
|
2938
2948
|
const merged = this.compositePixels({ paper: true }).data;
|
|
2939
|
-
const
|
|
2940
|
-
const
|
|
2941
|
-
|
|
2949
|
+
const changed = /* @__PURE__ */ new Map();
|
|
2950
|
+
const toStandard = (layers2) => layers2.map((l) => {
|
|
2951
|
+
const blend = l.blend === "pass-through" ? l.blend : _chunkSZ6KMZNMcjs.standardBlendMode.call(void 0, l.blend);
|
|
2952
|
+
if (blend !== l.blend) changed.set(l.blend, [..._nullishCoalesce(changed.get(l.blend), () => ( [])), l.name]);
|
|
2953
|
+
const next = blend === l.blend ? l : { ...l, blend };
|
|
2954
|
+
return next.type === "group" ? { ...next, children: toStandard(next.children) } : next;
|
|
2955
|
+
});
|
|
2956
|
+
const layers = toStandard(this.doc.layers);
|
|
2957
|
+
const result = _chunkFRD3FUXIcjs.exportPsd.call(void 0, { width, height, layers: [paperLayer, ...layers], merged, resolution: dpi });
|
|
2958
|
+
for (const [mode, names] of changed) {
|
|
2959
|
+
const label = _nullishCoalesce(_optionalChain([_chunkSZ6KMZNMcjs.BLEND_MODES, 'access', _72 => _72.find, 'call', _73 => _73((m) => m.id === mode), 'optionalAccess', _74 => _74.label]), () => ( mode));
|
|
2960
|
+
const std = _nullishCoalesce(_optionalChain([_chunkSZ6KMZNMcjs.BLEND_MODES, 'access', _75 => _75.find, 'call', _76 => _76((m) => m.id === _chunkSZ6KMZNMcjs.standardBlendMode.call(void 0, mode)), 'optionalAccess', _77 => _77.label]), () => ( _chunkSZ6KMZNMcjs.standardBlendMode.call(void 0, mode)));
|
|
2961
|
+
const list = names.map((n) => `"${n}"`).join(", ");
|
|
2962
|
+
const one = names.length === 1;
|
|
2963
|
+
result.warnings.push(`${label} blending has no PSD equivalent; ${list} ${one ? "was" : "were"} written as ${std}, the nearest Photoshop mode, so ${one ? "it looks" : "they look"} different in Photoshop (the merged image is exact).`);
|
|
2964
|
+
}
|
|
2942
2965
|
return result;
|
|
2943
2966
|
}
|
|
2944
2967
|
/** `render_preview` as a base64 PNG. */
|
|
2945
2968
|
previewPngBase64(options = {}) {
|
|
2946
2969
|
const img = this.renderPreview(options);
|
|
2947
|
-
return { data:
|
|
2970
|
+
return { data: _chunkT3QZ6S47cjs.bytesToBase64.call(void 0, _chunkT3QZ6S47cjs.encodePng.call(void 0, img.width, img.height, img.data)), width: img.width, height: img.height };
|
|
2948
2971
|
}
|
|
2949
2972
|
// --- Guides --------------------------------------------------------------------
|
|
2950
2973
|
setGuides(next) {
|
|
@@ -2982,17 +3005,17 @@ var PaintEditorController = (_class9 = class {
|
|
|
2982
3005
|
pixels = this.decodeImage(input.png.trim().startsWith("data:") ? input.png.trim() : `data:image/png;base64,${input.png.trim()}`, what);
|
|
2983
3006
|
} else throw new PaintEditorError(`${what}: pass png (a PNG as base64 or a data URL) or pixels.`);
|
|
2984
3007
|
if (pixels.width > MAX_IMAGE_SIDE || pixels.height > MAX_IMAGE_SIDE) throw new PaintEditorError(`${what} is ${pixels.width}\xD7${pixels.height}; the limit is ${MAX_IMAGE_SIDE} px per side.`);
|
|
2985
|
-
const src =
|
|
3008
|
+
const src = _chunkT3QZ6S47cjs.pngDataUrl.call(void 0, pixels.width, pixels.height, pixels.data);
|
|
2986
3009
|
this.imagePixels.set(src, pixels);
|
|
2987
3010
|
return { src, pixels };
|
|
2988
3011
|
}
|
|
2989
3012
|
decodeImage(src, what = "Image") {
|
|
2990
3013
|
const cached = this.imagePixels.get(src);
|
|
2991
3014
|
if (cached) return cached;
|
|
2992
|
-
const parsed =
|
|
3015
|
+
const parsed = _chunkT3QZ6S47cjs.parseDataUrl.call(void 0, src);
|
|
2993
3016
|
if (!parsed) throw new PaintEditorError(`${what} is not a data URL or base64 PNG.`);
|
|
2994
3017
|
try {
|
|
2995
|
-
const png =
|
|
3018
|
+
const png = _chunkT3QZ6S47cjs.decodePng.call(void 0, parsed.bytes);
|
|
2996
3019
|
const px = { width: png.width, height: png.height, data: png.data };
|
|
2997
3020
|
this.imagePixels.set(src, px);
|
|
2998
3021
|
return px;
|
|
@@ -3050,7 +3073,7 @@ var PaintEditorController = (_class9 = class {
|
|
|
3050
3073
|
const { src, pixels } = this.importImage(options, "The reference image");
|
|
3051
3074
|
const ref = {
|
|
3052
3075
|
id: `ref${this.nextReferenceId++}`,
|
|
3053
|
-
name: _optionalChain([options, 'access',
|
|
3076
|
+
name: _optionalChain([options, 'access', _78 => _78.name, 'optionalAccess', _79 => _79.trim, 'call', _80 => _80()]) || `Reference ${this.guides.references.length + 1}`,
|
|
3054
3077
|
src,
|
|
3055
3078
|
width: pixels.width,
|
|
3056
3079
|
height: pixels.height,
|
|
@@ -3129,7 +3152,7 @@ var PaintEditorController = (_class9 = class {
|
|
|
3129
3152
|
try {
|
|
3130
3153
|
const px = this.decodeImage(ref.src, `Reference "${ref.name}"`);
|
|
3131
3154
|
guides.references.push({ id: ref.id, name: String(_nullishCoalesce(ref.name, () => ( ref.id))), src: ref.src, width: px.width, height: px.height, x: Number(ref.x) || 0, y: Number(ref.y) || 0, displayWidth: Number(ref.displayWidth) || 240, visible: ref.visible !== false });
|
|
3132
|
-
const n = Number(_nullishCoalesce(_optionalChain([/^ref(\d+)$/, 'access',
|
|
3155
|
+
const n = Number(_nullishCoalesce(_optionalChain([/^ref(\d+)$/, 'access', _81 => _81.exec, 'call', _82 => _82(ref.id), 'optionalAccess', _83 => _83[1]]), () => ( 0)));
|
|
3133
3156
|
if (n >= this.nextReferenceId) this.nextReferenceId = n + 1;
|
|
3134
3157
|
} catch (e) {
|
|
3135
3158
|
problems.push(e.message);
|
|
@@ -3149,7 +3172,7 @@ var PaintEditorController = (_class9 = class {
|
|
|
3149
3172
|
}
|
|
3150
3173
|
addSwatch(color, name) {
|
|
3151
3174
|
const c = parseColor(color);
|
|
3152
|
-
this.swatches = [...this.swatches, _optionalChain([name, 'optionalAccess',
|
|
3175
|
+
this.swatches = [...this.swatches, _optionalChain([name, 'optionalAccess', _84 => _84.trim, 'call', _85 => _85()]) ? { color: c, name: name.trim() } : { color: c }];
|
|
3153
3176
|
this.emit([]);
|
|
3154
3177
|
return this.swatches;
|
|
3155
3178
|
}
|
|
@@ -3197,7 +3220,7 @@ var PaintEditorController = (_class9 = class {
|
|
|
3197
3220
|
}
|
|
3198
3221
|
/** A layer's tile surface (live while stroking), for thumbnails. */
|
|
3199
3222
|
layerSurface(id) {
|
|
3200
|
-
const l = _optionalChain([
|
|
3223
|
+
const l = _optionalChain([_chunkT3QZ6S47cjs.findLayer.call(void 0, this.currentLayers(), id), 'optionalAccess', _86 => _86.layer]);
|
|
3201
3224
|
return isPixelLayer(l) ? l.surface : null;
|
|
3202
3225
|
}
|
|
3203
3226
|
}, _class9);
|
|
@@ -3234,6 +3257,169 @@ function resampleInto(src, rect, width, height) {
|
|
|
3234
3257
|
return { width, height, data: out };
|
|
3235
3258
|
}
|
|
3236
3259
|
|
|
3260
|
+
// src/paint-editor/presence.ts
|
|
3261
|
+
var PaintPresence = class extends _chunkEGFUVXKKcjs.PresenceStore {
|
|
3262
|
+
};
|
|
3263
|
+
var FRAME = 16;
|
|
3264
|
+
function strokeSchedule(points) {
|
|
3265
|
+
if (points.length < 2) return points.map(() => 1);
|
|
3266
|
+
const t0 = points[0].t;
|
|
3267
|
+
const t1 = points[points.length - 1].t;
|
|
3268
|
+
if (points.every((p) => Number.isFinite(p.t)) && t1 > t0) {
|
|
3269
|
+
return points.map((p) => Math.min(1, Math.max(0, (p.t - t0) / (t1 - t0))));
|
|
3270
|
+
}
|
|
3271
|
+
const acc = [0];
|
|
3272
|
+
for (let i = 1; i < points.length; i++) acc.push(acc[i - 1] + Math.hypot(points[i].x - points[i - 1].x, points[i].y - points[i - 1].y));
|
|
3273
|
+
const total = acc[acc.length - 1];
|
|
3274
|
+
return total > 0 ? acc.map((d) => d / total) : points.map(() => 1);
|
|
3275
|
+
}
|
|
3276
|
+
function strokeDuration(points, max = 1800) {
|
|
3277
|
+
const t0 = _optionalChain([points, 'access', _87 => _87[0], 'optionalAccess', _88 => _88.t]);
|
|
3278
|
+
const t1 = _optionalChain([points, 'access', _89 => _89[points.length - 1], 'optionalAccess', _90 => _90.t]);
|
|
3279
|
+
let ms;
|
|
3280
|
+
if (points.every((p) => Number.isFinite(p.t)) && t1 > t0) ms = t1 - t0;
|
|
3281
|
+
else {
|
|
3282
|
+
let length = 0;
|
|
3283
|
+
for (let i = 1; i < points.length; i++) length += Math.hypot(points[i].x - points[i - 1].x, points[i].y - points[i - 1].y);
|
|
3284
|
+
ms = length / 1.5;
|
|
3285
|
+
}
|
|
3286
|
+
return Math.min(max, Math.max(250, ms));
|
|
3287
|
+
}
|
|
3288
|
+
function sweepPath(rect, rows = 4) {
|
|
3289
|
+
const inset = Math.min(rect.width, rect.height) * 0.08;
|
|
3290
|
+
const left = rect.x + inset;
|
|
3291
|
+
const right = rect.x + rect.width - inset;
|
|
3292
|
+
const out = [];
|
|
3293
|
+
for (let r = 0; r < rows; r++) {
|
|
3294
|
+
const y = rect.y + inset + (rect.height - 2 * inset) * (r + 0.5) / rows;
|
|
3295
|
+
out.push(r % 2 ? { x: right, y } : { x: left, y }, r % 2 ? { x: left, y } : { x: right, y });
|
|
3296
|
+
}
|
|
3297
|
+
return out;
|
|
3298
|
+
}
|
|
3299
|
+
var centre = (r) => ({ x: r.x + r.width / 2, y: r.y + r.height / 2 });
|
|
3300
|
+
var PaintDirector = class {
|
|
3301
|
+
constructor(controller, presence, options = {}) {
|
|
3302
|
+
this.controller = controller;
|
|
3303
|
+
this.presence = presence;
|
|
3304
|
+
this.options = options;
|
|
3305
|
+
this.clock = _nullishCoalesce(options.clock, () => ( _chunkEGFUVXKKcjs.realPresenceClock));
|
|
3306
|
+
this.queue = new (0, _chunkEGFUVXKKcjs.PerformanceQueue)(presence, { clock: this.clock, linger: options.linger });
|
|
3307
|
+
}
|
|
3308
|
+
|
|
3309
|
+
|
|
3310
|
+
|
|
3311
|
+
|
|
3312
|
+
|
|
3313
|
+
/** Acts out `commands` in order for `actor`. Resolves with one result per command. */
|
|
3314
|
+
perform(actor, commands) {
|
|
3315
|
+
return this.queue.run(actor, async () => {
|
|
3316
|
+
const results = [];
|
|
3317
|
+
for (const command of commands) {
|
|
3318
|
+
try {
|
|
3319
|
+
results.push({ ok: true, command, result: await this.performOne(actor.id, command) });
|
|
3320
|
+
} catch (error) {
|
|
3321
|
+
results.push({ ok: false, command, message: error instanceof Error ? error.message : String(error) });
|
|
3322
|
+
}
|
|
3323
|
+
}
|
|
3324
|
+
return results;
|
|
3325
|
+
});
|
|
3326
|
+
}
|
|
3327
|
+
ms(n) {
|
|
3328
|
+
return Math.round(n / Math.max(0.1, _nullishCoalesce(this.options.speed, () => ( 1))));
|
|
3329
|
+
}
|
|
3330
|
+
where(id) {
|
|
3331
|
+
const a = this.presence.get(id);
|
|
3332
|
+
return { x: _nullishCoalesce(_optionalChain([a, 'optionalAccess', _91 => _91.x]), () => ( 0)), y: _nullishCoalesce(_optionalChain([a, 'optionalAccess', _92 => _92.y]), () => ( 0)) };
|
|
3333
|
+
}
|
|
3334
|
+
/** Glides to `to`; an actor that just appeared starts there instead of the corner. */
|
|
3335
|
+
async glide(id, to, ms = 380) {
|
|
3336
|
+
const a = this.presence.get(id);
|
|
3337
|
+
if (!a || a.x === 0 && a.y === 0) {
|
|
3338
|
+
this.presence.set({ id, x: to.x, y: to.y });
|
|
3339
|
+
return;
|
|
3340
|
+
}
|
|
3341
|
+
await _chunkEGFUVXKKcjs.tweenPresenceCursor.call(void 0, this.presence, this.clock, id, this.where(id), to, this.ms(ms));
|
|
3342
|
+
}
|
|
3343
|
+
async say(id, text, ms) {
|
|
3344
|
+
if (!text) return;
|
|
3345
|
+
this.presence.set({ id, message: text });
|
|
3346
|
+
await this.clock.wait(this.ms(ms));
|
|
3347
|
+
}
|
|
3348
|
+
async performOne(id, command) {
|
|
3349
|
+
const c = this.controller;
|
|
3350
|
+
switch (command.kind) {
|
|
3351
|
+
case "say":
|
|
3352
|
+
await this.say(id, command.text, 900);
|
|
3353
|
+
return void 0;
|
|
3354
|
+
case "point":
|
|
3355
|
+
await this.say(id, command.note, 500);
|
|
3356
|
+
await this.glide(id, command.at);
|
|
3357
|
+
this.presence.set({ id, pressed: true });
|
|
3358
|
+
await this.clock.wait(this.ms(110));
|
|
3359
|
+
this.presence.set({ id, pressed: false });
|
|
3360
|
+
return void 0;
|
|
3361
|
+
case "stroke":
|
|
3362
|
+
await this.say(id, command.note, 500);
|
|
3363
|
+
return this.stroke(id, command.stroke);
|
|
3364
|
+
case "fill": {
|
|
3365
|
+
await this.say(id, command.note, 500);
|
|
3366
|
+
const { width, height } = c.getState().document.canvas;
|
|
3367
|
+
const path = sweepPath({ x: 0, y: 0, width, height });
|
|
3368
|
+
await this.glide(id, path[0]);
|
|
3369
|
+
this.presence.set({ id, pressed: true });
|
|
3370
|
+
try {
|
|
3371
|
+
for (let i = 1; i < path.length; i++) await _chunkEGFUVXKKcjs.tweenPresenceCursor.call(void 0, this.presence, this.clock, id, path[i - 1], path[i], this.ms(i % 2 ? 260 : 90));
|
|
3372
|
+
} finally {
|
|
3373
|
+
this.presence.set({ id, pressed: false });
|
|
3374
|
+
}
|
|
3375
|
+
return c.fillLayer(command.fill);
|
|
3376
|
+
}
|
|
3377
|
+
case "replay": {
|
|
3378
|
+
await this.say(id, command.note, 500);
|
|
3379
|
+
const source = c.getStrokes().filter((s) => _optionalChain([command, 'access', _93 => _93.replay, 'access', _94 => _94.strokeIds, 'optionalAccess', _95 => _95.includes, 'call', _96 => _96(s.id)]));
|
|
3380
|
+
const first = _optionalChain([source, 'access', _97 => _97[0], 'optionalAccess', _98 => _98.points, 'access', _99 => _99[0]]);
|
|
3381
|
+
if (first) await this.glide(id, first);
|
|
3382
|
+
const result = c.replayStrokes(command.replay);
|
|
3383
|
+
if (result.bounds) await this.glide(id, centre(result.bounds), 520);
|
|
3384
|
+
return result;
|
|
3385
|
+
}
|
|
3386
|
+
}
|
|
3387
|
+
}
|
|
3388
|
+
/** Paints a stroke live: begins it, pushes its points frame by frame as the cursor reaches them, then ends it (one undo step). */
|
|
3389
|
+
async stroke(id, init) {
|
|
3390
|
+
const c = this.controller;
|
|
3391
|
+
const points = c.checkPoints(init.points);
|
|
3392
|
+
const { points: _points, ...rest } = init;
|
|
3393
|
+
const session = c.beginStroke({ snapToPerspective: false, start: points[0], ...rest });
|
|
3394
|
+
try {
|
|
3395
|
+
await this.glide(id, points[0]);
|
|
3396
|
+
this.presence.set({ id, pressed: true });
|
|
3397
|
+
const at = strokeSchedule(points);
|
|
3398
|
+
const duration = this.ms(strokeDuration(points, this.options.maxStrokeMs));
|
|
3399
|
+
let next = 0;
|
|
3400
|
+
const frames = Math.max(1, Math.round(duration / FRAME));
|
|
3401
|
+
for (let f = 1; f <= frames; f++) {
|
|
3402
|
+
const t = f / frames;
|
|
3403
|
+
const from = next;
|
|
3404
|
+
while (next < points.length && at[next] <= t + 1e-9) next++;
|
|
3405
|
+
if (next > from) {
|
|
3406
|
+
session.push(points.slice(from, next));
|
|
3407
|
+
const p = points[next - 1];
|
|
3408
|
+
this.presence.set({ id, x: p.x, y: p.y });
|
|
3409
|
+
}
|
|
3410
|
+
if (f < frames) await this.clock.wait(duration / frames);
|
|
3411
|
+
}
|
|
3412
|
+
if (next < points.length) session.push(points.slice(next));
|
|
3413
|
+
this.presence.set({ id, pressed: false });
|
|
3414
|
+
return session.end();
|
|
3415
|
+
} catch (error) {
|
|
3416
|
+
if (c.activeStroke === session) session.cancel();
|
|
3417
|
+
this.presence.set({ id, pressed: false });
|
|
3418
|
+
throw error;
|
|
3419
|
+
}
|
|
3420
|
+
}
|
|
3421
|
+
};
|
|
3422
|
+
|
|
3237
3423
|
// src/paint-editor/guide-tools.ts
|
|
3238
3424
|
var READ = { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false };
|
|
3239
3425
|
var WRITE = { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: false };
|
|
@@ -3554,7 +3740,7 @@ function createPaintGuideTools(c) {
|
|
|
3554
3740
|
const pad = c.mixingPad;
|
|
3555
3741
|
return {
|
|
3556
3742
|
content: [
|
|
3557
|
-
{ type: "image", data:
|
|
3743
|
+
{ type: "image", data: _chunkT3QZ6S47cjs.bytesToBase64.call(void 0, _chunkT3QZ6S47cjs.encodePng.call(void 0, pad.width, pad.height, pad.pixels())), mimeType: "image/png" },
|
|
3558
3744
|
{ type: "text", text: `Mixing pad ${pad.width}\xD7${pad.height}` }
|
|
3559
3745
|
]
|
|
3560
3746
|
};
|
|
@@ -3575,7 +3761,7 @@ var TIP = {
|
|
|
3575
3761
|
type: "object",
|
|
3576
3762
|
description: "The tip (the shared brush engine). Missing fields keep their current values.",
|
|
3577
3763
|
properties: {
|
|
3578
|
-
size: { type: "number", minimum: 1, maximum:
|
|
3764
|
+
size: { type: "number", minimum: 1, maximum: _chunkHUFQD4CBcjs.MAX_BRUSH_SIZE, description: "Diameter in document pixels." },
|
|
3579
3765
|
hardness: { type: "number", minimum: 0, maximum: 1, description: "Edge hardness, 0 (soft) .. 1 (hard)." },
|
|
3580
3766
|
spacing: { type: "number", minimum: 0.01, maximum: 10, description: "Dab spacing as a fraction of the diameter (0.05 is smooth, 1 is dotted)." },
|
|
3581
3767
|
angle: { type: "number", minimum: -360, maximum: 360, description: "Tip angle in degrees, counter-clockwise; with rotation stroke or barrel it is added to the stroke direction or pen rotation." },
|
|
@@ -3585,7 +3771,11 @@ var TIP = {
|
|
|
3585
3771
|
smoothing: { type: "number", minimum: 0, maximum: 0.95, description: "Position smoothing of the input, 0..0.95." },
|
|
3586
3772
|
pressureSize: { type: "boolean", description: "Pressure scales the size (down to dynamics.minSize)." },
|
|
3587
3773
|
pressureOpacity: { type: "boolean", description: "Pressure scales the opacity." },
|
|
3588
|
-
blend: {
|
|
3774
|
+
blend: {
|
|
3775
|
+
type: "string",
|
|
3776
|
+
enum: _chunkSZ6KMZNMcjs.BLEND_MODES.map((m) => m.id),
|
|
3777
|
+
description: "How paint combines with the layer. pigment mixes it in like real paint (blue into yellow gives green); multiply darkens like marker ink; watercolor glazes like a transparent wash; tint, highlight and shadow recolour, light and shade (see list_blend_modes)."
|
|
3778
|
+
}
|
|
3589
3779
|
},
|
|
3590
3780
|
additionalProperties: false
|
|
3591
3781
|
};
|
|
@@ -3616,7 +3806,7 @@ var MIXER = {
|
|
|
3616
3806
|
mix: { type: "number", minimum: 0, maximum: 1, description: "How far each dab's paint moves from the reservoir towards the picked-up colour." },
|
|
3617
3807
|
loadEachStroke: { type: "boolean", description: "Refill the reservoir with the colour before each stroke." },
|
|
3618
3808
|
cleanEachStroke: { type: "boolean", description: "Empty the pickup well after each stroke." },
|
|
3619
|
-
mixing: { type: "string", enum: [...
|
|
3809
|
+
mixing: { type: "string", enum: [..._chunkHUFQD4CBcjs.MIXING_MODELS], description: "rgb: RGB averages. pigment: mixes like paint (Kubelka-Munk)." }
|
|
3620
3810
|
},
|
|
3621
3811
|
additionalProperties: false
|
|
3622
3812
|
};
|
|
@@ -3665,6 +3855,12 @@ function createPaintEditorToolProvider(controller, options = {}) {
|
|
|
3665
3855
|
const c = controller;
|
|
3666
3856
|
const tools = [];
|
|
3667
3857
|
const add = (t) => tools.push(t);
|
|
3858
|
+
const act = async (command, direct) => {
|
|
3859
|
+
if (!options.director) return direct();
|
|
3860
|
+
const [r] = await options.director.perform(_nullishCoalesce(options.actor, () => ( { id: "agent", name: "Agent" })), [command]);
|
|
3861
|
+
if (!r || !r.ok) throw new Error(r && !r.ok ? r.message : "The director did not run the command.");
|
|
3862
|
+
return r.result;
|
|
3863
|
+
};
|
|
3668
3864
|
add({
|
|
3669
3865
|
name: "get_canvas_info",
|
|
3670
3866
|
title: "Get the canvas",
|
|
@@ -3689,7 +3885,7 @@ function createPaintEditorToolProvider(controller, options = {}) {
|
|
|
3689
3885
|
strokes: d.strokes.length,
|
|
3690
3886
|
undo: s.undoLabel,
|
|
3691
3887
|
redo: s.redoLabel,
|
|
3692
|
-
blendModes:
|
|
3888
|
+
blendModes: _chunkSZ6KMZNMcjs.BLEND_MODES.map((m) => m.id)
|
|
3693
3889
|
};
|
|
3694
3890
|
}
|
|
3695
3891
|
});
|
|
@@ -3820,7 +4016,11 @@ function createPaintEditorToolProvider(controller, options = {}) {
|
|
|
3820
4016
|
name: { type: "string", minLength: 1, description: "New name." },
|
|
3821
4017
|
visible: { type: "boolean", description: "Show or hide." },
|
|
3822
4018
|
opacity: { type: "number", minimum: 0, maximum: 1, description: "Layer opacity 0..1." },
|
|
3823
|
-
blend: {
|
|
4019
|
+
blend: {
|
|
4020
|
+
type: "string",
|
|
4021
|
+
enum: [..._chunkSZ6KMZNMcjs.BLEND_MODES.map((m) => m.id), "pass-through"],
|
|
4022
|
+
description: "Blend mode (pass-through for groups only). Painterly modes: watercolor (the layer glazes like a transparent wash), tint (recolours keeping lightness), highlight (adds soft coloured light), shadow (shades with ambient fill); see list_blend_modes."
|
|
4023
|
+
},
|
|
3824
4024
|
clipped: { type: "boolean", description: "Clip to the layer below (paint only shows where it has paint)." },
|
|
3825
4025
|
locks: {
|
|
3826
4026
|
type: "object",
|
|
@@ -3840,6 +4040,22 @@ function createPaintEditorToolProvider(controller, options = {}) {
|
|
|
3840
4040
|
annotations: { title: "Change a layer", ...SET2 },
|
|
3841
4041
|
handler: ({ layerId, ...u }) => c.updateLayer(layerId, u)
|
|
3842
4042
|
});
|
|
4043
|
+
add({
|
|
4044
|
+
name: "list_blend_modes",
|
|
4045
|
+
title: "List blend modes",
|
|
4046
|
+
description: "Lists every layer and brush blend mode: id, label, group (standard Photoshop modes, pigment, or painterly), what the pigment and painterly modes do, and the standard mode PSD export writes in their place. Changes nothing. Read it before choosing a painterly mode for update_layer or a brush tip.",
|
|
4047
|
+
inputSchema: EMPTY2,
|
|
4048
|
+
annotations: { title: "List blend modes", ...READ2 },
|
|
4049
|
+
handler: () => ({
|
|
4050
|
+
modes: _chunkSZ6KMZNMcjs.BLEND_MODES.map((m) => ({
|
|
4051
|
+
id: m.id,
|
|
4052
|
+
label: m.label,
|
|
4053
|
+
group: m.painterly ? "painterly" : m.id === "pigment" ? "pigment" : "standard",
|
|
4054
|
+
...m.description ? { description: m.description } : {},
|
|
4055
|
+
psd: _chunkSZ6KMZNMcjs.standardBlendMode.call(void 0, m.id)
|
|
4056
|
+
}))
|
|
4057
|
+
})
|
|
4058
|
+
});
|
|
3843
4059
|
add({
|
|
3844
4060
|
name: "set_active_layer",
|
|
3845
4061
|
title: "Choose the active layer",
|
|
@@ -3904,12 +4120,12 @@ function createPaintEditorToolProvider(controller, options = {}) {
|
|
|
3904
4120
|
opacity: { type: "number", minimum: 0, maximum: 1, description: "Opacity 0..1 (default 1)." },
|
|
3905
4121
|
grain: { type: "number", minimum: 0, maximum: 1, description: "Paper grain response 0..1 (default 0: flat)." },
|
|
3906
4122
|
pressure: { type: "number", minimum: 0, maximum: 1, description: "With grain: how far into the valleys, 0..1 (default 0.5)." },
|
|
3907
|
-
blend: { type: "string", enum:
|
|
4123
|
+
blend: { type: "string", enum: _chunkSZ6KMZNMcjs.BLEND_MODES.map((m) => m.id), description: "Blend mode (default normal; pigment mixes like paint, watercolor glazes; see list_blend_modes)." }
|
|
3908
4124
|
},
|
|
3909
4125
|
additionalProperties: false
|
|
3910
4126
|
},
|
|
3911
4127
|
annotations: { title: "Fill a layer", ...WRITE2 },
|
|
3912
|
-
handler: (a) => c.fillLayer(a)
|
|
4128
|
+
handler: (a) => act({ kind: "fill", fill: a }, () => c.fillLayer(a))
|
|
3913
4129
|
});
|
|
3914
4130
|
add({
|
|
3915
4131
|
name: "clear_layer",
|
|
@@ -3927,7 +4143,7 @@ function createPaintEditorToolProvider(controller, options = {}) {
|
|
|
3927
4143
|
annotations: { title: "List brushes", ...READ2 },
|
|
3928
4144
|
handler: () => {
|
|
3929
4145
|
const s = c.getState();
|
|
3930
|
-
return { activeBrushId: s.brush.id, activeEdited: !s.brush.builtin && Boolean(_optionalChain([c, 'access',
|
|
4146
|
+
return { activeBrushId: s.brush.id, activeEdited: !s.brush.builtin && Boolean(_optionalChain([c, 'access', _100 => _100.getBrush, 'call', _101 => _101(s.brush.id), 'optionalAccess', _102 => _102.builtin])), brushes: s.brushes.map(brushSummary) };
|
|
3931
4147
|
}
|
|
3932
4148
|
});
|
|
3933
4149
|
add({
|
|
@@ -4025,7 +4241,7 @@ function createPaintEditorToolProvider(controller, options = {}) {
|
|
|
4025
4241
|
const t = c.brushThumbnail(_nullishCoalesce(id, () => ( c.getState().brush.id)), { width, height, color });
|
|
4026
4242
|
return {
|
|
4027
4243
|
content: [
|
|
4028
|
-
{ type: "image", data:
|
|
4244
|
+
{ type: "image", data: _chunkT3QZ6S47cjs.bytesToBase64.call(void 0, _chunkT3QZ6S47cjs.encodePng.call(void 0, t.width, t.height, t.data)), mimeType: "image/png" },
|
|
4029
4245
|
{ type: "text", text: `Brush ${_nullishCoalesce(id, () => ( c.getState().brush.id))} ${t.width}\xD7${t.height}` }
|
|
4030
4246
|
]
|
|
4031
4247
|
};
|
|
@@ -4092,7 +4308,7 @@ function createPaintEditorToolProvider(controller, options = {}) {
|
|
|
4092
4308
|
add({
|
|
4093
4309
|
name: "paint_stroke",
|
|
4094
4310
|
title: "Paint a brush stroke",
|
|
4095
|
-
description: "Paints one stroke through points (document pixels, with optional pressure, time, tilt and barrel rotation) on a pixel layer with a library brush or the active one, optionally changed for this stroke. Grain-responsive brushes follow the paper; the mixer engine (mixer-brush, blender, smudge) picks up and moves paint already on the layer. The symmetry guide adds its mirror copies; with a tracing image that samples colours, a stroke without color takes the image colour at its first point. One undo step. Returns the layer id, changed bounds, dab count, the recorded strokeId (for replay_strokes) and, for the mixer, its load after the stroke.",
|
|
4311
|
+
description: "Paints one stroke through points (document pixels, with optional pressure, time, tilt and barrel rotation) on a pixel layer with a library brush or the active one, optionally changed for this stroke. Grain-responsive brushes follow the paper; the mixer engine (mixer-brush, blender, smudge) picks up and moves paint already on the layer. The symmetry guide adds its mirror copies; with a tracing image that samples colours, a stroke without color takes the image colour at its first point. With an agent cursor (a director), the stroke is painted live along the points at the pace of their times. One undo step. Returns the layer id, changed bounds, dab count, the recorded strokeId (for replay_strokes) and, for the mixer, its load after the stroke.",
|
|
4096
4312
|
inputSchema: {
|
|
4097
4313
|
type: "object",
|
|
4098
4314
|
properties: {
|
|
@@ -4108,8 +4324,9 @@ function createPaintEditorToolProvider(controller, options = {}) {
|
|
|
4108
4324
|
additionalProperties: false
|
|
4109
4325
|
},
|
|
4110
4326
|
annotations: { title: "Paint a brush stroke", ...WRITE2 },
|
|
4111
|
-
handler: (a) => {
|
|
4112
|
-
const
|
|
4327
|
+
handler: async (a) => {
|
|
4328
|
+
const stroke = { points: a.points, layerId: a.layerId, brushId: a.brushId, brush: a.brush, color: a.color, seed: a.seed, snapToPerspective: a.snapToPerspective };
|
|
4329
|
+
const r = await act({ kind: "stroke", stroke }, () => c.paintStroke(stroke));
|
|
4113
4330
|
return r.mixerLoad ? { ...r, mixerLoad: loadResult(r.mixerLoad) } : r;
|
|
4114
4331
|
}
|
|
4115
4332
|
});
|
|
@@ -4146,7 +4363,7 @@ function createPaintEditorToolProvider(controller, options = {}) {
|
|
|
4146
4363
|
color: s.color,
|
|
4147
4364
|
points: ids ? s.points : s.points.length,
|
|
4148
4365
|
seed: s.seed,
|
|
4149
|
-
copies: _nullishCoalesce(_optionalChain([s, 'access',
|
|
4366
|
+
copies: _nullishCoalesce(_optionalChain([s, 'access', _103 => _103.copies, 'optionalAccess', _104 => _104.length]), () => ( 0)),
|
|
4150
4367
|
bounds: { x: Math.floor(Math.min(...xs) - pad), y: Math.floor(Math.min(...ys) - pad), width: Math.ceil(Math.max(...xs) - Math.min(...xs) + 2 * pad), height: Math.ceil(Math.max(...ys) - Math.min(...ys) + 2 * pad) }
|
|
4151
4368
|
};
|
|
4152
4369
|
})
|
|
@@ -4183,7 +4400,10 @@ function createPaintEditorToolProvider(controller, options = {}) {
|
|
|
4183
4400
|
additionalProperties: false
|
|
4184
4401
|
},
|
|
4185
4402
|
annotations: { title: "Replay strokes, varied", ...WRITE2 },
|
|
4186
|
-
handler: (a) =>
|
|
4403
|
+
handler: (a) => {
|
|
4404
|
+
const replay = a;
|
|
4405
|
+
return act({ kind: "replay", replay }, () => c.replayStrokes(replay));
|
|
4406
|
+
}
|
|
4187
4407
|
});
|
|
4188
4408
|
add({
|
|
4189
4409
|
name: "set_view",
|
|
@@ -4276,18 +4496,18 @@ function createPaintEditorToolProvider(controller, options = {}) {
|
|
|
4276
4496
|
annotations: { title: "Export the painting", ...READ2 },
|
|
4277
4497
|
handler: async ({ format, quality, scale, paper }) => {
|
|
4278
4498
|
const bytes = await c.exportImage({ format, quality, scale, paper });
|
|
4279
|
-
return { mimeType: _nullishCoalesce(format, () => ( "image/png")), bytes: bytes.length, data:
|
|
4499
|
+
return { mimeType: _nullishCoalesce(format, () => ( "image/png")), bytes: bytes.length, data: _chunkT3QZ6S47cjs.bytesToBase64.call(void 0, bytes) };
|
|
4280
4500
|
}
|
|
4281
4501
|
});
|
|
4282
4502
|
add({
|
|
4283
4503
|
name: "export_psd",
|
|
4284
4504
|
title: "Export as PSD",
|
|
4285
|
-
description: 'Writes the painting as an 8-bit RGB PSD (PSB above 30000 px) through the shared PSD writer: every layer and group with its opacity, blend, mask and locks, the paper as a locked "Paper" pixel layer at the bottom, and the composite as the merged image. Changes nothing. Returns the file as base64, its size, whether it is a PSB, and warnings (pigment
|
|
4505
|
+
description: 'Writes the painting as an 8-bit RGB PSD (PSB above 30000 px) through the shared PSD writer: every layer and group with its opacity, blend, mask and locks, the paper as a locked "Paper" pixel layer at the bottom, and the composite as the merged image. Changes nothing. Returns the file as base64, its size, whether it is a PSB, and warnings (pigment and painterly blend modes have no PSD equivalent: they are written as the nearest standard mode, see list_blend_modes).',
|
|
4286
4506
|
inputSchema: EMPTY2,
|
|
4287
4507
|
annotations: { title: "Export as PSD", ...READ2 },
|
|
4288
4508
|
handler: () => {
|
|
4289
4509
|
const r = c.exportPsd();
|
|
4290
|
-
return { data:
|
|
4510
|
+
return { data: _chunkT3QZ6S47cjs.bytesToBase64.call(void 0, r.bytes), bytes: r.bytes.length, psb: r.psb, warnings: r.warnings };
|
|
4291
4511
|
}
|
|
4292
4512
|
});
|
|
4293
4513
|
add({
|
|
@@ -4311,7 +4531,7 @@ function createPaintEditorToolProvider(controller, options = {}) {
|
|
|
4311
4531
|
}
|
|
4312
4532
|
});
|
|
4313
4533
|
tools.push(...createPaintGuideTools(c));
|
|
4314
|
-
tools.push(...
|
|
4534
|
+
tools.push(..._chunkHUFQD4CBcjs.createPigmentTools.call(void 0, ));
|
|
4315
4535
|
return { id: _nullishCoalesce(options.id, () => ( "paint-editor")), namespace: options.namespace, tools };
|
|
4316
4536
|
}
|
|
4317
4537
|
|
|
@@ -4417,12 +4637,12 @@ var PaintGesture = (_class10 = class {
|
|
|
4417
4637
|
if (!m || m.pointerId !== e.pointerId) return;
|
|
4418
4638
|
this.mode = null;
|
|
4419
4639
|
this.predicted = [];
|
|
4420
|
-
if (m.kind === "stroke") _optionalChain([this, 'access',
|
|
4640
|
+
if (m.kind === "stroke") _optionalChain([this, 'access', _105 => _105.controller, 'access', _106 => _106.activeStroke, 'optionalAccess', _107 => _107.end, 'call', _108 => _108()]);
|
|
4421
4641
|
}
|
|
4422
4642
|
cancel() {
|
|
4423
4643
|
this.penDown = false;
|
|
4424
4644
|
this.predicted = [];
|
|
4425
|
-
if (_optionalChain([this, 'access',
|
|
4645
|
+
if (_optionalChain([this, 'access', _109 => _109.mode, 'optionalAccess', _110 => _110.kind]) === "stroke") _optionalChain([this, 'access', _111 => _111.controller, 'access', _112 => _112.activeStroke, 'optionalAccess', _113 => _113.cancel, 'call', _114 => _114()]);
|
|
4426
4646
|
this.mode = null;
|
|
4427
4647
|
}
|
|
4428
4648
|
get active() {
|
|
@@ -4506,11 +4726,11 @@ var PaintCanvasPresenter = (_class11 = class {
|
|
|
4506
4726
|
const key = `${tx},${ty}`;
|
|
4507
4727
|
if (this.uploaded.get(key) === data) return;
|
|
4508
4728
|
this.uploaded.set(key, data);
|
|
4509
|
-
if (!this.scratch) this.scratch = ctx.createImageData(
|
|
4729
|
+
if (!this.scratch) this.scratch = ctx.createImageData(_chunkSZ6KMZNMcjs.TILE, _chunkSZ6KMZNMcjs.TILE);
|
|
4510
4730
|
this.scratch.data.set(data);
|
|
4511
|
-
const ox = tx *
|
|
4512
|
-
const oy = ty *
|
|
4513
|
-
ctx.putImageData(this.scratch, ox, oy, 0, 0, Math.min(
|
|
4731
|
+
const ox = tx * _chunkSZ6KMZNMcjs.TILE;
|
|
4732
|
+
const oy = ty * _chunkSZ6KMZNMcjs.TILE;
|
|
4733
|
+
ctx.putImageData(this.scratch, ox, oy, 0, 0, Math.min(_chunkSZ6KMZNMcjs.TILE, width - ox), Math.min(_chunkSZ6KMZNMcjs.TILE, height - oy));
|
|
4514
4734
|
drawn++;
|
|
4515
4735
|
}, { dirty });
|
|
4516
4736
|
return drawn;
|
|
@@ -4550,7 +4770,7 @@ var PAPER_SLIDERS = [
|
|
|
4550
4770
|
];
|
|
4551
4771
|
function readPath(obj, path) {
|
|
4552
4772
|
let v = obj;
|
|
4553
|
-
for (const k of path.split(".")) v = _optionalChain([v, 'optionalAccess',
|
|
4773
|
+
for (const k of path.split(".")) v = _optionalChain([v, 'optionalAccess', _115 => _115[k]]);
|
|
4554
4774
|
return typeof v === "number" ? v : 0;
|
|
4555
4775
|
}
|
|
4556
4776
|
function patchPath(obj, path, value) {
|
|
@@ -4591,6 +4811,19 @@ function wheelPick(dx, dy, wheel, color) {
|
|
|
4591
4811
|
const [nr, ng, nb] = hsvToRgb(wheelToHue(wheelAngle(dx, dy), wheel), s || 1, v || 1);
|
|
4592
4812
|
return rgbToHexColor(nr, ng, nb);
|
|
4593
4813
|
}
|
|
4814
|
+
var BLEND_MENU_GROUPS = [
|
|
4815
|
+
{ label: "Standard", modes: _chunkSZ6KMZNMcjs.BLEND_MODES.filter((m) => !m.painterly && m.id !== "pigment") },
|
|
4816
|
+
{ label: "Paint", modes: _chunkSZ6KMZNMcjs.BLEND_MODES.filter((m) => m.painterly || m.id === "pigment") }
|
|
4817
|
+
];
|
|
4818
|
+
|
|
4819
|
+
|
|
4820
|
+
|
|
4821
|
+
|
|
4822
|
+
|
|
4823
|
+
|
|
4824
|
+
|
|
4825
|
+
|
|
4826
|
+
|
|
4594
4827
|
|
|
4595
4828
|
|
|
4596
4829
|
|
|
@@ -4729,5 +4962,5 @@ function wheelPick(dx, dy, wheel, color) {
|
|
|
4729
4962
|
|
|
4730
4963
|
|
|
4731
4964
|
|
|
4732
|
-
exports.BLEND_MODES =
|
|
4965
|
+
exports.BLEND_MENU_GROUPS = BLEND_MENU_GROUPS; exports.BLEND_MODES = _chunkSZ6KMZNMcjs.BLEND_MODES; exports.BRUSH_ID = BRUSH_ID; exports.BRUSH_ROTATIONS = BRUSH_ROTATIONS; exports.BRUSH_SLIDERS = BRUSH_SLIDERS; exports.BUILTIN_BRUSHES = BUILTIN_BRUSHES; exports.DEFAULT_BRUSH_ID = DEFAULT_BRUSH_ID; exports.DEFAULT_DPI = DEFAULT_DPI; exports.DEFAULT_DYNAMICS = DEFAULT_DYNAMICS; exports.DEFAULT_PAPER = DEFAULT_PAPER; exports.DEFAULT_SWATCHES = DEFAULT_SWATCHES; exports.DEFAULT_VIEW = DEFAULT_VIEW; exports.DryStroke = DryStroke; exports.GRAIN_PATTERNS = GRAIN_PATTERNS; exports.GRAIN_TILE = GRAIN_TILE; exports.HARMONY_KINDS = HARMONY_KINDS; exports.IDENTITY_AFFINE = IDENTITY_AFFINE; exports.IDENTITY_COPY = IDENTITY_COPY; exports.MAX_BRUSH_SIZE = _chunkHUFQD4CBcjs.MAX_BRUSH_SIZE; exports.MAX_CANVAS_SIDE = MAX_CANVAS_SIDE; exports.MAX_COORDINATE = MAX_COORDINATE; exports.MAX_IMAGE_SIDE = MAX_IMAGE_SIDE; exports.MAX_ZOOM = MAX_ZOOM; exports.MIN_CANVAS_SIDE = MIN_CANVAS_SIDE; exports.MIN_ZOOM = MIN_ZOOM; exports.MIXING_PAD_HEIGHT = MIXING_PAD_HEIGHT; exports.MIXING_PAD_WIDTH = MIXING_PAD_WIDTH; exports.MixingPad = MixingPad; exports.PAINTERLY_BLEND_MODES = _chunkSZ6KMZNMcjs.PAINTERLY_BLEND_MODES; exports.PAINT_BRUSH_CATEGORIES = PAINT_BRUSH_CATEGORIES; exports.PAINT_BRUSH_ENGINES = PAINT_BRUSH_ENGINES; exports.PAINT_FORMAT = PAINT_FORMAT; exports.PAINT_SCHEMA_VERSION = PAINT_SCHEMA_VERSION; exports.PAINT_TOOLS = PAINT_TOOLS; exports.PAPER_FAMILIES = PAPER_FAMILIES; exports.PAPER_LIBRARY = PAPER_LIBRARY; exports.PAPER_NODE_ID = PAPER_NODE_ID; exports.PAPER_SLIDERS = PAPER_SLIDERS; exports.PaintCanvasPresenter = PaintCanvasPresenter; exports.PaintDirector = PaintDirector; exports.PaintDocumentError = PaintDocumentError; exports.PaintEditorController = PaintEditorController; exports.PaintEditorError = PaintEditorError; exports.PaintGesture = PaintGesture; exports.PaintPresence = PaintPresence; exports.PaintStrokeSession = PaintStrokeSession; exports.PaperGrain = PaperGrain; exports.PenDabWalker = PenDabWalker; exports.PenSmoother = PenSmoother; exports.PerspectiveSnapper = PerspectiveSnapper; exports.SNAP_DECIDE_DISTANCE = SNAP_DECIDE_DISTANCE; exports.SYMMETRY_MODES = SYMMETRY_MODES; exports.TRACING_NODE_ID = TRACING_NODE_ID; exports.TileableNoise = TileableNoise; exports.affineCopy = affineCopy; exports.applyAffine = applyAffine; exports.brushToJSON = brushToJSON; exports.clonePaper = clonePaper; exports.colorHarmony = colorHarmony; exports.composeAffine = composeAffine; exports.createPaintCompositor = createPaintCompositor; exports.createPaintDocument = createPaintDocument; exports.createPaintEditorToolProvider = createPaintEditorToolProvider; exports.createPaintLayer = createPaintLayer; exports.decodeImageBlob = decodeImageBlob; exports.defaultGuides = defaultGuides; exports.defaultImageEncoder = defaultImageEncoder; exports.deserializePaintDocument = deserializePaintDocument; exports.deserializePaintDocumentAsync = deserializePaintDocumentAsync; exports.documentExtensions = documentExtensions; exports.documentToScreen = documentToScreen; exports.downloadBytes = downloadBytes; exports.downsampleRgba = downsampleRgba; exports.fitZoom = fitZoom; exports.grainCatch = grainCatch; exports.grainHeights = grainHeights; exports.guideOverlay = guideOverlay; exports.handlePaintShortcut = handlePaintShortcut; exports.hash2 = hash2; exports.hexToRgb8 = hexToRgb8; exports.hslToRgb = hslToRgb; exports.hsvToRgb = hsvToRgb; exports.hueToWheel = hueToWheel; exports.invertAffine = invertAffine; exports.isBlendMode = _chunkSZ6KMZNMcjs.isBlendMode; exports.isPainterlyBlendMode = _chunkSZ6KMZNMcjs.isPainterlyBlendMode; exports.isPalmTouch = isPalmTouch; exports.mapPenPoint = mapPenPoint; exports.mix32 = mix32; exports.mixerLoadForStroke = mixerLoadForStroke; exports.mixerTip = mixerTip; exports.newPaintLayerId = newPaintLayerId; exports.normalizeBrushStroke = normalizeBrushStroke; exports.normalizeCanvas = normalizeCanvas; exports.normalizeDynamics = normalizeDynamics; exports.normalizePaintBrush = normalizePaintBrush; exports.normalizePaper = normalizePaper; exports.normalizePerspective = normalizePerspective; exports.normalizeRotation = normalizeRotation; exports.normalizeSymmetry = normalizeSymmetry; exports.normalizeView = normalizeView; exports.paperGrain = paperGrain; exports.paperKey = paperKey; exports.paperNode = paperNode; exports.paperPreset = paperPreset; exports.parseBrushLibrary = parseBrushLibrary; exports.parseHexColor = parseHexColor; exports.patchPath = patchPath; exports.penOrientation = penOrientation; exports.perspectiveDirections = perspectiveDirections; exports.perspectiveGuideLines = perspectiveGuideLines; exports.pointerToPenPoint = pointerToPenPoint; exports.rand01 = rand01; exports.randSigned = randSigned; exports.readPath = readPath; exports.renderBrushThumbnail = renderBrushThumbnail; exports.renderColorWheel = renderColorWheel; exports.renderPaper = renderPaper; exports.rgbToHexColor = rgbToHexColor; exports.rgbToHsl = rgbToHsl; exports.rgbToHsv = rgbToHsv; exports.samplePressure = samplePressure; exports.screenToDocument = screenToDocument; exports.seedFromString = seedFromString; exports.serializePaintDocument = serializePaintDocument; exports.serializePaintDocumentExternal = serializePaintDocumentExternal; exports.standardBlendMode = _chunkSZ6KMZNMcjs.standardBlendMode; exports.strokeBounds = strokeBounds; exports.strokeDuration = strokeDuration; exports.strokeSchedule = strokeSchedule; exports.sweepPath = sweepPath; exports.symmetryAxisAngles = symmetryAxisAngles; exports.symmetryAxisSegments = symmetryAxisSegments; exports.symmetryCopies = symmetryCopies; exports.thumbnailStroke = thumbnailStroke; exports.tiltToOrientation = tiltToOrientation; exports.toStrokePoint = toStrokePoint; exports.variationAffine = variationAffine; exports.varyStroke = varyStroke; exports.viewCssTransform = viewCssTransform; exports.viewMatrix = viewMatrix; exports.viewPenToDocument = viewPenToDocument; exports.wheelAngle = wheelAngle; exports.wheelPick = wheelPick; exports.wheelPoint = wheelPoint; exports.wheelToHue = wheelToHue;
|
|
4733
4966
|
//# sourceMappingURL=index.cjs.map
|