@pixerate/editor 0.275.1 → 0.276.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/animation-editor/index.cjs +62 -62
- package/dist/animation-editor/index.js +6 -6
- package/dist/brushes/index.cjs +81 -70
- package/dist/brushes/index.js +17 -6
- package/dist/brushes/patch.d.cts +1 -1
- package/dist/brushes/patch.d.ts +1 -1
- package/dist/brushes/profiles.d.cts +2 -0
- package/dist/brushes/profiles.d.ts +2 -0
- package/dist/brushes/schema.d.cts +1 -0
- package/dist/brushes/schema.d.ts +1 -0
- package/dist/brushes/types.d.cts +22 -1
- package/dist/brushes/types.d.ts +22 -1
- package/dist/{brushstrokeRender-WGY4DZHF.js → brushstrokeRender-FK3ASUUJ.js} +5 -5
- package/dist/{brushstrokeRender-2RQL46WB.cjs → brushstrokeRender-I6MYFCOU.cjs} +21 -21
- package/dist/canvas/index.cjs +13 -13
- package/dist/canvas/index.js +1 -1
- package/dist/{chunk-Y2ISSVPH.js → chunk-4EM5NGCL.js} +167 -9
- package/dist/{chunk-Y354ETAE.cjs → chunk-5HR5CSLC.cjs} +49 -49
- package/dist/{chunk-LMG57L5A.js → chunk-CTHWXW5M.js} +121 -8
- package/dist/{chunk-43XJC3PP.js → chunk-CVBTJVRN.js} +1 -1
- package/dist/{chunk-RJGW3RQS.js → chunk-GHYJAMMS.js} +1 -1
- package/dist/{chunk-NIBFKXMD.cjs → chunk-IFWLZZCW.cjs} +619 -2
- package/dist/{chunk-G5TCMKX5.js → chunk-IJ6NSWKM.js} +2 -2
- package/dist/{chunk-C6VB7CPY.cjs → chunk-ISCAJBPQ.cjs} +1 -1
- package/dist/{chunk-W6JDUXP3.js → chunk-J23JOHPR.js} +1 -1
- package/dist/{chunk-IEEY5RJV.js → chunk-JNMNM3SL.js} +1 -1
- package/dist/{chunk-HVO6XCI4.js → chunk-JPB65KQ6.js} +1 -1
- package/dist/{chunk-ACTHSQOI.js → chunk-LDZOXESA.js} +618 -1
- package/dist/{chunk-DHC4E2DU.cjs → chunk-MITQGHN3.cjs} +121 -8
- package/dist/{chunk-STLTOISW.cjs → chunk-NPPMKMCU.cjs} +17 -17
- package/dist/{chunk-75SYKUOT.js → chunk-OS6OG7DN.js} +1 -1
- package/dist/{chunk-OLZXXAER.cjs → chunk-OY24XRYF.cjs} +408 -250
- package/dist/{chunk-6QNDGMK7.cjs → chunk-Q33V5PEF.cjs} +123 -42
- package/dist/{chunk-JDXWLCXF.cjs → chunk-QNNZA3V5.cjs} +2 -2
- package/dist/{chunk-T6KNJVBP.cjs → chunk-U26LUXCJ.cjs} +35 -35
- package/dist/{chunk-62MFUHSI.cjs → chunk-UQXULAMQ.cjs} +16 -16
- package/dist/{chunk-RAPNRK4R.cjs → chunk-X7XBEX3O.cjs} +88 -88
- package/dist/{chunk-MSWLJI4G.js → chunk-XMSH66VU.js} +2 -2
- package/dist/{chunk-ZM7IKQ4X.js → chunk-XVPQNX7O.js} +89 -8
- package/dist/{chunk-YYZC2EQO.cjs → chunk-ZIE6EJGR.cjs} +23 -23
- package/dist/image-editor/index.cjs +880 -852
- package/dist/image-editor/index.js +36 -8
- package/dist/paint/index.cjs +33 -5
- package/dist/paint/index.d.cts +1 -0
- package/dist/paint/index.d.ts +1 -0
- package/dist/paint/index.js +32 -4
- package/dist/paint/live-patterns.d.cts +149 -0
- package/dist/paint/live-patterns.d.ts +149 -0
- package/dist/paint/wet/world.d.cts +13 -0
- package/dist/paint/wet/world.d.ts +13 -0
- package/dist/paint-editor/brush-model.d.cts +7 -1
- package/dist/paint-editor/brush-model.d.ts +7 -1
- package/dist/paint-editor/controller.d.cts +52 -0
- package/dist/paint-editor/controller.d.ts +52 -0
- package/dist/paint-editor/index.cjs +850 -510
- package/dist/paint-editor/index.js +355 -15
- package/dist/paint-editor/ui.d.cts +5 -1
- package/dist/paint-editor/ui.d.ts +5 -1
- package/dist/paint-editor/wet-tools.d.cts +42 -0
- package/dist/paint-editor/wet-tools.d.ts +42 -0
- package/dist/paint-editor/wet.d.cts +22 -1
- package/dist/paint-editor/wet.d.ts +22 -1
- package/dist/vector/index.cjs +1002 -1002
- package/dist/vector/index.js +7 -7
- package/package.json +1 -1
|
@@ -19,7 +19,11 @@ var _chunkWOFXZ3XUcjs = require('./chunk-WOFXZ3XU.cjs');
|
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
var _chunkIFWLZZCWcjs = require('./chunk-IFWLZZCW.cjs');
|
|
23
27
|
|
|
24
28
|
|
|
25
29
|
var _chunk2VX55NFMcjs = require('./chunk-2VX55NFM.cjs');
|
|
@@ -278,6 +282,29 @@ var BRUSH_PRESETS = [
|
|
|
278
282
|
behaviour: { surface: "wet", exchange: { pickup: 0.4, mix: 0.4 }, wet: { water: 0.8, pigment: 0.45, rewet: 0.2 } },
|
|
279
283
|
colour: { default: { type: "gradient", stops: [{ offset: 0, color: "paint" }, { offset: 1, color: "secondary" }], space: "pigment", map: { by: "distance", length: 500, repeat: "mirror", unit: "px" } } }
|
|
280
284
|
},
|
|
285
|
+
// Live patterns: Gray-Scott reaction-diffusion that grows inside the wet wash and freezes as it dries.
|
|
286
|
+
{
|
|
287
|
+
id: "turing-wash",
|
|
288
|
+
name: "Turing wash",
|
|
289
|
+
kind: "mark",
|
|
290
|
+
medium: "paint",
|
|
291
|
+
variety: "watercolor",
|
|
292
|
+
tip: { shape: "round", size: 36, hardness: 0.5, spacing: 0.12 },
|
|
293
|
+
dynamics: { smoothing: 0.25, pressureOpacity: true, minSize: 0.35 },
|
|
294
|
+
behaviour: { surface: "wet", exchange: { pickup: 0.45 }, wet: { water: 0.75, pigment: 0.55, rewet: 0.2 } },
|
|
295
|
+
livePatterns: { pattern: "spots", contrast: 1.2, secondColor: "#0ea5e9", relief: 0.25 }
|
|
296
|
+
},
|
|
297
|
+
{
|
|
298
|
+
id: "coral-ink",
|
|
299
|
+
name: "Coral ink",
|
|
300
|
+
kind: "mark",
|
|
301
|
+
medium: "ink",
|
|
302
|
+
variety: "watercolor",
|
|
303
|
+
tip: { shape: "round", size: 22, hardness: 0.65, spacing: 0.12 },
|
|
304
|
+
dynamics: { smoothing: 0.3, pressureOpacity: true, minSize: 0.3 },
|
|
305
|
+
behaviour: { surface: "wet", exchange: { pickup: 0.35 }, wet: { water: 0.7, pigment: 0.75, rewet: 0.15 } },
|
|
306
|
+
livePatterns: { pattern: "coral", scale: 1.2, contrast: 1.3 }
|
|
307
|
+
},
|
|
281
308
|
{
|
|
282
309
|
id: "watercolor-detail",
|
|
283
310
|
name: "Watercolour rigger",
|
|
@@ -1152,6 +1179,12 @@ function countAndFlip(raw, base) {
|
|
|
1152
1179
|
return { ...n > 1 ? { count: n } : {}, ...flip !== "none" ? { flip } : {} };
|
|
1153
1180
|
}
|
|
1154
1181
|
var withTipGrain = (g) => g ? { tipGrain: g } : {};
|
|
1182
|
+
var withLivePatterns = (lp) => lp ? { livePatterns: lp } : {};
|
|
1183
|
+
function readLivePatterns(raw, base) {
|
|
1184
|
+
if (raw === null) return null;
|
|
1185
|
+
if (!raw || typeof raw !== "object") return base;
|
|
1186
|
+
return _chunkIFWLZZCWcjs.normalizeLivePatterns.call(void 0, raw, _nullishCoalesce(base, () => ( _chunkIFWLZZCWcjs.DEFAULT_LIVE_PATTERNS)));
|
|
1187
|
+
}
|
|
1155
1188
|
function readTipGrain(raw, base) {
|
|
1156
1189
|
if (raw === null) return null;
|
|
1157
1190
|
if (!raw || typeof raw !== "object") return base;
|
|
@@ -1250,12 +1283,12 @@ function normalizePaintBrush(raw = {}, base) {
|
|
|
1250
1283
|
if (rb.dirty !== void 0) mixerIn.cleanEachStroke = !rb.dirty;
|
|
1251
1284
|
if (rb.mixing !== void 0) mixerIn.mixing = rb.mixing;
|
|
1252
1285
|
}
|
|
1253
|
-
const mixer =
|
|
1286
|
+
const mixer = _chunkIFWLZZCWcjs.normalizeMixer.call(void 0, mixerIn);
|
|
1254
1287
|
let behavior = normalizeBehavior(rb, b.behavior);
|
|
1255
1288
|
if (engine === "mixer") behavior = { ...behavior, pickup: mixer.wet, mix: mixer.mix, dirty: !mixer.cleanEachStroke, mixing: mixer.mixing };
|
|
1256
1289
|
let paint = _nullishCoalesce(b.paint, () => ( null));
|
|
1257
1290
|
if (raw.paint !== void 0) {
|
|
1258
|
-
const p =
|
|
1291
|
+
const p = _chunkIFWLZZCWcjs.readPaintSource.call(void 0, raw.paint);
|
|
1259
1292
|
paint = p && p.type === "gradient" ? p : null;
|
|
1260
1293
|
} else if (rb.multicolor !== void 0) {
|
|
1261
1294
|
const mc = normalizeMultiColor(rb.multicolor, _nullishCoalesce(paintToMultiColor(paint), () => ( DEFAULT_MULTI_COLOR)));
|
|
@@ -1275,7 +1308,7 @@ function normalizePaintBrush(raw = {}, base) {
|
|
|
1275
1308
|
name: typeof raw.name === "string" && raw.name.trim() ? raw.name.trim().slice(0, 80) : b.name,
|
|
1276
1309
|
category: PAINT_BRUSH_CATEGORIES.includes(raw.category) ? raw.category : b.category,
|
|
1277
1310
|
engine,
|
|
1278
|
-
tip:
|
|
1311
|
+
tip: _chunkIFWLZZCWcjs.normalizeBrush.call(void 0, { ...b.tip, ..._nullishCoalesce(raw.tip, () => ( {})) }),
|
|
1279
1312
|
grain: unit2(raw.grain, b.grain),
|
|
1280
1313
|
pressureSmoothing: range(raw.pressureSmoothing, 0, 0.95, b.pressureSmoothing),
|
|
1281
1314
|
rotation: BRUSH_ROTATIONS.includes(raw.rotation) ? raw.rotation : b.rotation,
|
|
@@ -1283,8 +1316,8 @@ function normalizePaintBrush(raw = {}, base) {
|
|
|
1283
1316
|
mixer,
|
|
1284
1317
|
loadsColor: typeof raw.loadsColor === "boolean" ? raw.loadsColor : b.loadsColor,
|
|
1285
1318
|
behavior,
|
|
1286
|
-
blender:
|
|
1287
|
-
smudge:
|
|
1319
|
+
blender: _chunkIFWLZZCWcjs.normalizeBlender.call(void 0, _nullishCoalesce(raw.blender, () => ( {})), b.blender),
|
|
1320
|
+
smudge: _chunkIFWLZZCWcjs.normalizeSmudge.call(void 0, _nullishCoalesce(raw.smudge, () => ( {})), b.smudge),
|
|
1288
1321
|
wet,
|
|
1289
1322
|
impasto: normalizeImpasto(_nullishCoalesce(raw.impasto, () => ( {})), _nullishCoalesce(b.impasto, () => ( DEFAULT_IMPASTO))),
|
|
1290
1323
|
particle: normalizeParticle(_nullishCoalesce(raw.particle, () => ( {})), _nullishCoalesce(b.particle, () => ( DEFAULT_PARTICLE))),
|
|
@@ -1299,6 +1332,7 @@ function normalizePaintBrush(raw = {}, base) {
|
|
|
1299
1332
|
stamp: readStamp(raw.stamp, _nullishCoalesce(b.stamp, () => ( null))),
|
|
1300
1333
|
spray: readSpray(raw.spray, _nullishCoalesce(b.spray, () => ( null))),
|
|
1301
1334
|
...withTipGrain(readTipGrain(raw.tipGrain, _nullishCoalesce(b.tipGrain, () => ( null)))),
|
|
1335
|
+
...withLivePatterns(readLivePatterns(raw.livePatterns, _nullishCoalesce(b.livePatterns, () => ( null)))),
|
|
1302
1336
|
paint,
|
|
1303
1337
|
...raw.builtin ? { builtin: true } : {}
|
|
1304
1338
|
};
|
|
@@ -1308,16 +1342,16 @@ var BASE_BRUSH = {
|
|
|
1308
1342
|
name: "Round",
|
|
1309
1343
|
category: "custom",
|
|
1310
1344
|
engine: "dab",
|
|
1311
|
-
tip: { ...
|
|
1345
|
+
tip: { ..._chunkIFWLZZCWcjs.DEFAULT_BRUSH },
|
|
1312
1346
|
grain: 0,
|
|
1313
1347
|
pressureSmoothing: 0,
|
|
1314
1348
|
rotation: "fixed",
|
|
1315
1349
|
dynamics: { ...DEFAULT_DYNAMICS },
|
|
1316
|
-
mixer: { ...
|
|
1350
|
+
mixer: { ..._chunkIFWLZZCWcjs.DEFAULT_MIXER },
|
|
1317
1351
|
loadsColor: true,
|
|
1318
1352
|
behavior: { ...DEFAULT_BEHAVIOR, multicolor: { ...DEFAULT_MULTI_COLOR, colors: [] } },
|
|
1319
|
-
blender: { ...
|
|
1320
|
-
smudge: { ...
|
|
1353
|
+
blender: { ..._chunkIFWLZZCWcjs.DEFAULT_BLENDER },
|
|
1354
|
+
smudge: { ..._chunkIFWLZZCWcjs.DEFAULT_SMUDGE },
|
|
1321
1355
|
wet: { ...DEFAULT_WET_BRUSH },
|
|
1322
1356
|
impasto: { ...DEFAULT_IMPASTO },
|
|
1323
1357
|
particle: { ...DEFAULT_PARTICLE },
|
|
@@ -1352,6 +1386,23 @@ var ONE_STAMP = {
|
|
|
1352
1386
|
toEngine: (v) => _nullishCoalesce(v[0], () => ( null)),
|
|
1353
1387
|
toFacet: (v) => v ? [v] : void 0
|
|
1354
1388
|
};
|
|
1389
|
+
var LIVE_PATTERNS_MAP = {
|
|
1390
|
+
toEngine: (v) => v !== null && typeof v === "object" ? JSON.parse(JSON.stringify(v)) : v,
|
|
1391
|
+
toFacet: (v) => {
|
|
1392
|
+
if (!v || typeof v !== "object") return void 0;
|
|
1393
|
+
const lp = v;
|
|
1394
|
+
const preset = _nullishCoalesce(_chunkIFWLZZCWcjs.LIVE_PATTERN_PRESETS[lp.pattern], () => ( _chunkIFWLZZCWcjs.LIVE_PATTERN_PRESETS.spots));
|
|
1395
|
+
return {
|
|
1396
|
+
pattern: lp.pattern,
|
|
1397
|
+
...lp.feed !== preset.feed ? { feed: lp.feed } : {},
|
|
1398
|
+
...lp.kill !== preset.kill ? { kill: lp.kill } : {},
|
|
1399
|
+
...lp.scale !== _chunkIFWLZZCWcjs.DEFAULT_LIVE_PATTERNS.scale ? { scale: lp.scale } : {},
|
|
1400
|
+
...lp.contrast !== _chunkIFWLZZCWcjs.DEFAULT_LIVE_PATTERNS.contrast ? { contrast: lp.contrast } : {},
|
|
1401
|
+
...lp.secondColor !== null ? { secondColor: lp.secondColor } : {},
|
|
1402
|
+
...lp.relief !== _chunkIFWLZZCWcjs.DEFAULT_LIVE_PATTERNS.relief ? { relief: lp.relief } : {}
|
|
1403
|
+
};
|
|
1404
|
+
}
|
|
1405
|
+
};
|
|
1355
1406
|
var f = (facet, engine, engines = ALL, extra = {}) => ({ facet, engine, engines, ...extra });
|
|
1356
1407
|
var each = (facetPrefix, enginePrefix, keys, engines) => keys.map((k) => f(`${facetPrefix}.${k}`, `${enginePrefix}.${k}`, engines));
|
|
1357
1408
|
var BRUSH_FIELDS = [
|
|
@@ -1390,6 +1441,7 @@ var BRUSH_FIELDS = [
|
|
|
1390
1441
|
f("behaviour.strength", "wet.strength", ["wet"]),
|
|
1391
1442
|
// Surfaces.
|
|
1392
1443
|
...each("behaviour.wet", "wet", ["medium", "water", "pigment", "body", "rewet", "load", "thinner"], ["wet"]),
|
|
1444
|
+
f("livePatterns", "livePatterns", ["wet"], { map: LIVE_PATTERNS_MAP }),
|
|
1393
1445
|
...each("ghost", "ghost", ["linger", "smear", "trigger"], ["wet"]),
|
|
1394
1446
|
...each("mutation", "mutation", ["settle", "patience", "fade"], ["dab", "wet", "impasto", "particle", "bristle"]),
|
|
1395
1447
|
f("behaviour.thick.applicator", "impasto.tool", ["impasto"]),
|
|
@@ -1486,6 +1538,7 @@ function resolveBrush(brush, options = {}) {
|
|
|
1486
1538
|
if (brush.iridescence && FILM.includes(engine)) input.iridescence = { ..._nullishCoalesce(input.iridescence, () => ( {})) };
|
|
1487
1539
|
if (engine === "wet") {
|
|
1488
1540
|
setPath(input, "wet.tool", brush.kind === "tool" ? WET_TOOL_OF[brush.tool] : "paint");
|
|
1541
|
+
if (brush.kind === "tool") delete input.livePatterns;
|
|
1489
1542
|
const medium = resolveWetMedium(brush);
|
|
1490
1543
|
if (medium) setPath(input, "wet.medium", medium);
|
|
1491
1544
|
if (brush.kind !== "tool" && brush.ghost) input.ghost = { ..._nullishCoalesce(input.ghost, () => ( {})) };
|
|
@@ -1574,7 +1627,7 @@ function skeleton(b) {
|
|
|
1574
1627
|
}
|
|
1575
1628
|
}
|
|
1576
1629
|
}
|
|
1577
|
-
var ORDER = ["id", "name", "description", "tags", "kind", "medium", "variety", "tool", "tip", "marks", "dynamics", "behaviour", "light", "fluorescence", "thermochromic", "iridescence", "ghost", "mutation", "motion", "colour"];
|
|
1630
|
+
var ORDER = ["id", "name", "description", "tags", "kind", "medium", "variety", "tool", "tip", "marks", "dynamics", "behaviour", "light", "fluorescence", "thermochromic", "iridescence", "ghost", "mutation", "motion", "livePatterns", "colour"];
|
|
1578
1631
|
function migrateBrushV1(raw) {
|
|
1579
1632
|
const b = normalizePaintBrush(raw);
|
|
1580
1633
|
const brush = skeleton(b);
|
|
@@ -1621,7 +1674,7 @@ var STAMP = {
|
|
|
1621
1674
|
pattern: BRUSH_STAMP_PATTERN,
|
|
1622
1675
|
description: `A sticker ref provider:id (find_stickers lists them; the editor's own are ${_chunkRDFHWAHLcjs.STAMP_KINDS.map((k) => `editor:${k}`).join(", ")}), or an image source source:<id> (list_brush_sources lists them; add_brush_source makes one from an image). A bare editor stamp (star) means editor:star.`
|
|
1623
1676
|
};
|
|
1624
|
-
var TIP_GRAIN_PATTERNS =
|
|
1677
|
+
var TIP_GRAIN_PATTERNS = _chunkIFWLZZCWcjs.GRAIN_PATTERNS.filter((p) => p !== "smooth");
|
|
1625
1678
|
var BRUSH_GRAIN_SOURCE_PATTERN = `^(?:source:[a-z0-9][a-z0-9-]{0,63}|${TIP_GRAIN_PATTERNS.join("|")})$`;
|
|
1626
1679
|
var TIP_GRAIN = object(
|
|
1627
1680
|
"Texture inside the tip (a grain source), separate from the paper's grain: each dab is multiplied by it. Continuous and scatter marks of round and stamp tips.",
|
|
@@ -1647,7 +1700,7 @@ var TIP = object(
|
|
|
1647
1700
|
"The tip: its shape and the dab it lays.",
|
|
1648
1701
|
{
|
|
1649
1702
|
shape: oneOf2(BRUSH_TIP_SHAPES, "round, flat, chisel: an ellipse set by roundness and angle (the name is for people); bristle: a tuft of bristles (see bristle); stamp: dabs shaped like a stamp, a sticker or an image source (see stamps), also laid as sprays, objects or particles."),
|
|
1650
|
-
size: num(1,
|
|
1703
|
+
size: num(1, _chunkIFWLZZCWcjs.MAX_BRUSH_SIZE, "Diameter in px (default 20)."),
|
|
1651
1704
|
hardness: unit3("Edge hardness, 0 soft .. 1 hard (default 1). Image-source stamps fade towards their edges below 1."),
|
|
1652
1705
|
spacing: num(0.01, 10, "Dab spacing as a fraction of the diameter: 0.05 smooth, 1 dotted (default 0.1)."),
|
|
1653
1706
|
angle: num(-360, 360, "Tip angle in degrees, counter-clockwise; added to the stroke direction or barrel with dynamics.rotation (default 0)."),
|
|
@@ -1818,6 +1871,19 @@ var MOTION = object("Animation after painting.", {
|
|
|
1818
1871
|
fps: int(1, 60, "Suggested playback rate in frames per second."),
|
|
1819
1872
|
waveSpeed: unit3("Particle waves: how fast they run by stroke time; 0 they stand still (default 0), 1 about four a second.")
|
|
1820
1873
|
});
|
|
1874
|
+
var LIVE_PATTERNS = object("Gray-Scott reaction-diffusion patterns (spots, stripes, coral, maze, worms) that grow inside wet paint (behaviour.surface: wet) and freeze where the paint dries.", {
|
|
1875
|
+
pattern: oneOf2(_chunkIFWLZZCWcjs.LIVE_PATTERN_KINDS, "Named Pearson feed/kill preset: spots (default, dividing mitosis spots), stripes (labyrinthine stripes), coral (branching dendrites), maze (winding channels) or worms (vermicular tracks)."),
|
|
1876
|
+
feed: num(0.01, 0.1, "Gray-Scott feed rate F (0.01..0.1; default from pattern)."),
|
|
1877
|
+
kill: num(0.03, 0.08, "Gray-Scott kill rate k (0.03..0.08; default from pattern)."),
|
|
1878
|
+
scale: num(0.5, 4, "Spatial scale of the pattern (diffusion multiplier, 0.5..4, default 1)."),
|
|
1879
|
+
contrast: num(0, 2, "Visual contrast of the V concentration field (0..2, default 1)."),
|
|
1880
|
+
secondColor: {
|
|
1881
|
+
type: ["string", "null"],
|
|
1882
|
+
pattern: "^#[0-9a-fA-F]{6}$",
|
|
1883
|
+
description: "Optional second colour (#rrggbb) that V blends the wet paint towards; null or omitted modulates pigment density/contrast."
|
|
1884
|
+
},
|
|
1885
|
+
relief: unit3("Impasto relief height written to the layer thick map as patterns grow (0..1, default 0).")
|
|
1886
|
+
});
|
|
1821
1887
|
var SOLID = {
|
|
1822
1888
|
type: "string",
|
|
1823
1889
|
pattern: "^(#([0-9a-fA-F]{6}|[0-9a-fA-F]{8})|rgba?\\(\\s*\\d{1,3}\\s*,\\s*\\d{1,3}\\s*,\\s*\\d{1,3}\\s*(,\\s*(0|1|0?\\.\\d+)\\s*)?\\))$",
|
|
@@ -1847,7 +1913,7 @@ var EFFECT = object(
|
|
|
1847
1913
|
);
|
|
1848
1914
|
var PAINT = {
|
|
1849
1915
|
description: "A colour a brush can carry: a solid colour, a light / dark pair, a gradient or effect paint.",
|
|
1850
|
-
anyOf: [SOLID, DUAL,
|
|
1916
|
+
anyOf: [SOLID, DUAL, _chunkIFWLZZCWcjs.PAINT_GRADIENT_JSON_SCHEMA, EFFECT]
|
|
1851
1917
|
};
|
|
1852
1918
|
var COLOUR = object("The brush's colours. The user's colour still wins unless own is set.", {
|
|
1853
1919
|
default: {
|
|
@@ -1882,6 +1948,7 @@ var BRUSH_JSON_SCHEMA = object(
|
|
|
1882
1948
|
ghost: GHOST,
|
|
1883
1949
|
mutation: MUTATION,
|
|
1884
1950
|
motion: MOTION,
|
|
1951
|
+
livePatterns: LIVE_PATTERNS,
|
|
1885
1952
|
colour: COLOUR
|
|
1886
1953
|
},
|
|
1887
1954
|
["id", "name", "kind", "tip"]
|
|
@@ -1899,6 +1966,7 @@ var BRUSH_FACET_SCHEMAS = {
|
|
|
1899
1966
|
ghost: GHOST,
|
|
1900
1967
|
mutation: MUTATION,
|
|
1901
1968
|
motion: MOTION,
|
|
1969
|
+
livePatterns: LIVE_PATTERNS,
|
|
1902
1970
|
colour: COLOUR,
|
|
1903
1971
|
paint: PAINT
|
|
1904
1972
|
};
|
|
@@ -2047,17 +2115,19 @@ function read(value, schema, path, problems) {
|
|
|
2047
2115
|
problems.push(`${path} must be ${JSON.stringify(schema.const)}; dropped.`);
|
|
2048
2116
|
return void 0;
|
|
2049
2117
|
}
|
|
2050
|
-
|
|
2118
|
+
if (value === null && Array.isArray(schema.type) && schema.type.includes("null")) return null;
|
|
2119
|
+
const schemaType = Array.isArray(schema.type) ? schema.type[0] : schema.type;
|
|
2120
|
+
switch (schemaType) {
|
|
2051
2121
|
case "number":
|
|
2052
2122
|
case "integer": {
|
|
2053
2123
|
if (typeof value !== "number" || !Number.isFinite(value)) {
|
|
2054
2124
|
problems.push(`${path} must be a number; dropped.`);
|
|
2055
2125
|
return void 0;
|
|
2056
2126
|
}
|
|
2057
|
-
let n =
|
|
2127
|
+
let n = schemaType === "integer" ? Math.round(value) : value;
|
|
2058
2128
|
if (schema.minimum !== void 0 && n < schema.minimum) n = schema.minimum;
|
|
2059
2129
|
if (schema.maximum !== void 0 && n > schema.maximum) n = schema.maximum;
|
|
2060
|
-
if (n !== value) problems.push(`${path} ${value} is out of range (${schema.minimum}..${schema.maximum}${
|
|
2130
|
+
if (n !== value) problems.push(`${path} ${value} is out of range (${schema.minimum}..${schema.maximum}${schemaType === "integer" ? ", whole" : ""}); set to ${n}.`);
|
|
2061
2131
|
return n;
|
|
2062
2132
|
}
|
|
2063
2133
|
case "boolean":
|
|
@@ -2070,7 +2140,8 @@ function read(value, schema, path, problems) {
|
|
|
2070
2140
|
problems.push(`${path} ${JSON.stringify(value)} is not valid${schema.enum ? `; use one of ${schema.enum.join(", ")}` : ""}; dropped.`);
|
|
2071
2141
|
return void 0;
|
|
2072
2142
|
}
|
|
2073
|
-
|
|
2143
|
+
const s = schema.pattern === "^#[0-9a-fA-F]{6}$" ? value.toLowerCase() : value;
|
|
2144
|
+
return schema.maxLength !== void 0 ? s.slice(0, schema.maxLength) : s;
|
|
2074
2145
|
}
|
|
2075
2146
|
case "array": {
|
|
2076
2147
|
if (!Array.isArray(value)) {
|
|
@@ -2117,7 +2188,7 @@ function readPaint(value, path, problems) {
|
|
|
2117
2188
|
if (typeof value === "string") {
|
|
2118
2189
|
if (SOLID2.test(value.trim())) return value.trim().toLowerCase();
|
|
2119
2190
|
} else if (isObject(value) && value.type === "gradient") {
|
|
2120
|
-
const g =
|
|
2191
|
+
const g = _chunkIFWLZZCWcjs.readPaintSource.call(void 0, value);
|
|
2121
2192
|
if (g && g.type === "gradient") return g;
|
|
2122
2193
|
} else if (isObject(value) && value.type === "effect") {
|
|
2123
2194
|
if (!_chunkWOFXZ3XUcjs.validateJsonSchema.call(void 0, value, BRUSH_FACET_SCHEMAS.paint.anyOf[3]).length) return clone(value);
|
|
@@ -2145,8 +2216,8 @@ function normalizeBrushSpec(raw, problems = []) {
|
|
|
2145
2216
|
if (_optionalChain([out, 'access', _29 => _29.thermochromic, 'optionalAccess', _30 => _30.hotColor])) out.thermochromic.hotColor = out.thermochromic.hotColor.toLowerCase();
|
|
2146
2217
|
const brush = { id: raw.id, name, ...out, kind, ...tool ? { tool } : {}, tip: _nullishCoalesce(out.tip, () => ( { shape: "round" })) };
|
|
2147
2218
|
const ordered = () => {
|
|
2148
|
-
const { id, name: n, description, tags, kind: k, medium, variety, tool: t, tip, marks, dynamics, behaviour, light, fluorescence, thermochromic, iridescence, ghost, mutation, motion, colour } = brush;
|
|
2149
|
-
const all = { id, name: n, description, tags, kind: k, medium, variety, tool: t, tip, marks, dynamics, behaviour, light, fluorescence, thermochromic, iridescence, ghost, mutation, motion, colour };
|
|
2219
|
+
const { id, name: n, description, tags, kind: k, medium, variety, tool: t, tip, marks, dynamics, behaviour, light, fluorescence, thermochromic, iridescence, ghost, mutation, motion, livePatterns, colour } = brush;
|
|
2220
|
+
const all = { id, name: n, description, tags, kind: k, medium, variety, tool: t, tip, marks, dynamics, behaviour, light, fluorescence, thermochromic, iridescence, ghost, mutation, motion, livePatterns, colour };
|
|
2150
2221
|
return Object.fromEntries(Object.entries(all).filter(([, v]) => v !== void 0));
|
|
2151
2222
|
};
|
|
2152
2223
|
if (!out.tip) problems.push("tip is missing; a round tip is used.");
|
|
@@ -2279,8 +2350,12 @@ function normalizeBrushSpec(raw, problems = []) {
|
|
|
2279
2350
|
delete b.exchange;
|
|
2280
2351
|
}
|
|
2281
2352
|
}
|
|
2353
|
+
if (brush.livePatterns && (kind !== "mark" || _optionalChain([brush, 'access', _52 => _52.behaviour, 'optionalAccess', _53 => _53.surface]) !== "wet" || _optionalChain([brush, 'access', _54 => _54.marks, 'optionalAccess', _55 => _55.kind]) === "particles" || _optionalChain([brush, 'access', _56 => _56.marks, 'optionalAccess', _57 => _57.kind]) === "objects" || brush.tip.shape === "bristle")) {
|
|
2354
|
+
drop("livePatterns", "only wet paint brushes grow live patterns (set behaviour.surface to wet)");
|
|
2355
|
+
delete brush.livePatterns;
|
|
2356
|
+
}
|
|
2282
2357
|
if (brush.ghost) {
|
|
2283
|
-
if (kind === "tool" || _optionalChain([brush, 'access',
|
|
2358
|
+
if (kind === "tool" || _optionalChain([brush, 'access', _58 => _58.behaviour, 'optionalAccess', _59 => _59.surface]) !== "wet") {
|
|
2284
2359
|
drop("ghost", "it needs a mark brush with behaviour.surface wet");
|
|
2285
2360
|
delete brush.ghost;
|
|
2286
2361
|
} else {
|
|
@@ -2288,7 +2363,7 @@ function normalizeBrushSpec(raw, problems = []) {
|
|
|
2288
2363
|
drop("light", "ghost paint uses the wet light channel as its tracer");
|
|
2289
2364
|
delete brush.light;
|
|
2290
2365
|
}
|
|
2291
|
-
if (_optionalChain([brush, 'access',
|
|
2366
|
+
if (_optionalChain([brush, 'access', _60 => _60.behaviour, 'optionalAccess', _61 => _61.exchange])) {
|
|
2292
2367
|
drop("behaviour.exchange", "ghost paint does not pick paint up");
|
|
2293
2368
|
delete brush.behaviour.exchange;
|
|
2294
2369
|
}
|
|
@@ -2318,6 +2393,7 @@ var PAINT_PROFILE = {
|
|
|
2318
2393
|
tilt: "full",
|
|
2319
2394
|
tipGrain: "full",
|
|
2320
2395
|
dabCount: "full",
|
|
2396
|
+
livePatterns: "full",
|
|
2321
2397
|
iridescence: "full"
|
|
2322
2398
|
};
|
|
2323
2399
|
var IMAGE_PROFILE = {
|
|
@@ -2386,27 +2462,28 @@ function checkBrush(brush, profile) {
|
|
|
2386
2462
|
const image = brush.tip.shape === "stamp" && (_nullishCoalesce(brush.tip.stamps, () => ( []))).some(isBrushSourceRef);
|
|
2387
2463
|
add("tip.shape", "error", `${host} can't lay a ${image ? "stamp tip (image tips are stamps)" : `${brush.tip.shape} tip`}.`, `Set tip.shape to one of: ${list(profile.tipShapes)}.`);
|
|
2388
2464
|
}
|
|
2389
|
-
const marks = _nullishCoalesce(_optionalChain([brush, 'access',
|
|
2465
|
+
const marks = _nullishCoalesce(_optionalChain([brush, 'access', _62 => _62.marks, 'optionalAccess', _63 => _63.kind]), () => ( "continuous"));
|
|
2390
2466
|
if (!profile.marks.includes(marks)) add("marks", "error", `${host} can't lay ${marks} marks.`, `Use marks ${list(profile.marks)} (remove marks for continuous dabs).`);
|
|
2391
|
-
const surface = _nullishCoalesce(_optionalChain([brush, 'access',
|
|
2467
|
+
const surface = _nullishCoalesce(_optionalChain([brush, 'access', _64 => _64.behaviour, 'optionalAccess', _65 => _65.surface]), () => ( "dry"));
|
|
2392
2468
|
if (brush.kind === "mark" && !profile.surfaces.includes(surface)) add("behaviour.surface", "error", `${host} has no ${surface} surface.`, `Set behaviour.surface to ${list(profile.surfaces)}.`);
|
|
2393
|
-
const ex = _optionalChain([brush, 'access',
|
|
2394
|
-
feature(profile.reservoir, !!_optionalChain([ex, 'optionalAccess',
|
|
2395
|
-
feature(profile.exchange, !_optionalChain([ex, 'optionalAccess',
|
|
2396
|
-
feature(profile.grain, nonZero(_optionalChain([brush, 'access',
|
|
2397
|
-
feature(profile.light, nonZero(_optionalChain([brush, 'access',
|
|
2469
|
+
const ex = _optionalChain([brush, 'access', _66 => _66.behaviour, 'optionalAccess', _67 => _67.exchange]);
|
|
2470
|
+
feature(profile.reservoir, !!_optionalChain([ex, 'optionalAccess', _68 => _68.reservoir]), "behaviour.exchange.reservoir", "a Mixer Brush reservoir", "Remove behaviour.exchange.reservoir.");
|
|
2471
|
+
feature(profile.exchange, !_optionalChain([ex, 'optionalAccess', _69 => _69.reservoir]) && (nonZero(_optionalChain([ex, 'optionalAccess', _70 => _70.pickup])) || !!_optionalChain([ex, 'optionalAccess', _71 => _71.dirty])), "behaviour.exchange", "picking paint up", "Remove behaviour.exchange.");
|
|
2472
|
+
feature(profile.grain, nonZero(_optionalChain([brush, 'access', _72 => _72.behaviour, 'optionalAccess', _73 => _73.grain])), "behaviour.grain", "paper grain", "Set behaviour.grain to 0.");
|
|
2473
|
+
feature(profile.light, nonZero(_optionalChain([brush, 'access', _74 => _74.light, 'optionalAccess', _75 => _75.amount])), "light", "light paint (glow and spill)", "Remove light (or set light.amount to 0).");
|
|
2474
|
+
feature(_nullishCoalesce(profile.livePatterns, () => ( "none")), Boolean(brush.livePatterns), "livePatterns", "live reaction-diffusion patterns", "Remove livePatterns.");
|
|
2398
2475
|
const smartInks = profile.id === "paint" ? "full" : "none";
|
|
2399
|
-
feature(smartInks, nonZero(_optionalChain([brush, 'access',
|
|
2400
|
-
feature(smartInks, Boolean(_optionalChain([brush, 'access',
|
|
2476
|
+
feature(smartInks, nonZero(_optionalChain([brush, 'access', _76 => _76.fluorescence, 'optionalAccess', _77 => _77.amount])), "fluorescence", "UV-fluorescent ink", "Remove fluorescence (or set fluorescence.amount to 0).");
|
|
2477
|
+
feature(smartInks, Boolean(_optionalChain([brush, 'access', _78 => _78.thermochromic, 'optionalAccess', _79 => _79.hotColor])), "thermochromic", "thermochromic ink", "Remove thermochromic.");
|
|
2401
2478
|
feature(_nullishCoalesce(profile.iridescence, () => ( "none")), !!brush.iridescence, "iridescence", "thin-film iridescence", "Remove iridescence.");
|
|
2402
2479
|
feature(profile.surfaces.includes("wet") && profile.light === "full" ? "full" : "none", !!brush.ghost, "ghost", "ghost paint", "Remove ghost.");
|
|
2403
2480
|
if (brush.mutation) {
|
|
2404
2481
|
if (profile.id !== "paint") feature("none", true, "mutation", "mutation paint", "Remove mutation.");
|
|
2405
2482
|
else if (brush.kind === "tool") add("mutation", "error", "Tools work on paint already down and cannot be mutation brushes.", "Use a mark brush, or remove mutation.");
|
|
2406
|
-
else if (_optionalChain([brush, 'access',
|
|
2407
|
-
else if (_optionalChain([ex, 'optionalAccess',
|
|
2408
|
-
else if (nonZero(_optionalChain([ex, 'optionalAccess',
|
|
2409
|
-
else if (surface === "wet" && nonZero(_optionalChain([brush, 'access',
|
|
2483
|
+
else if (_optionalChain([brush, 'access', _80 => _80.marks, 'optionalAccess', _81 => _81.kind]) === "objects") add("mutation", "error", "Sticker brushes place objects rather than paint strokes and cannot be mutation brushes.", "Remove marks (or use continuous marks), or remove mutation.");
|
|
2484
|
+
else if (_optionalChain([ex, 'optionalAccess', _82 => _82.reservoir])) add("mutation", "error", "A Mixer Brush reads paint from the layer beneath and cannot be a mutation brush.", "Remove behaviour.exchange.reservoir, or remove mutation.");
|
|
2485
|
+
else if (nonZero(_optionalChain([ex, 'optionalAccess', _83 => _83.pickup])) || !!_optionalChain([ex, 'optionalAccess', _84 => _84.dirty])) add("mutation", "error", "Mutation brushes must lay their own colour without picking up paint from beneath.", "Remove behaviour.exchange (or set pickup to 0 and dirty to false), or remove mutation.");
|
|
2486
|
+
else if (surface === "wet" && nonZero(_optionalChain([brush, 'access', _85 => _85.light, 'optionalAccess', _86 => _86.amount]))) add("mutation", "error", "Wet mutation brushes use the wet light channel as their fade tracer.", "Remove light (or set light.amount to 0), or remove mutation.");
|
|
2410
2487
|
}
|
|
2411
2488
|
const m = brush.motion;
|
|
2412
2489
|
feature(profile.motion, !!m && (!!m.live || nonZero(m.waveSpeed) || m.fps !== void 0), "motion", "animation", "Remove motion.");
|
|
@@ -2416,16 +2493,16 @@ function checkBrush(brush, profile) {
|
|
|
2416
2493
|
feature(profile.velocity, nonZero(d.velocitySize) || nonZero(d.velocityOpacity), "dynamics.velocity", "velocity dynamics (its strokes carry no timing)", "Set dynamics.velocitySize and velocityOpacity to 0.");
|
|
2417
2494
|
feature(profile.tilt, nonZero(d.tiltSize) || nonZero(d.tiltRoundness) || nonZero(d.tiltOpacity), "dynamics.tilt", "tilt dynamics", "Set dynamics.tiltSize, tiltRoundness and tiltOpacity to 0.");
|
|
2418
2495
|
const colour = brush.colour;
|
|
2419
|
-
if (_optionalChain([colour, 'optionalAccess',
|
|
2496
|
+
if (_optionalChain([colour, 'optionalAccess', _87 => _87.default]) !== void 0) {
|
|
2420
2497
|
const kind = brushColourKind(colour.default);
|
|
2421
2498
|
if (!profile.colours.includes(kind)) add("colour.default", "error", `${host} can't paint ${kind} colours.`, `Use a ${list(profile.colours)} colour, or remove colour.default.`);
|
|
2422
2499
|
}
|
|
2423
|
-
const foreign = [...new Set((_nullishCoalesce(_optionalChain([colour, 'optionalAccess',
|
|
2500
|
+
const foreign = [...new Set((_nullishCoalesce(_optionalChain([colour, 'optionalAccess', _88 => _88.palette]), () => ( []))).map(brushColourKind).filter((k) => !profile.colours.includes(k)))];
|
|
2424
2501
|
if (foreign.length) add("colour.palette", "warning", `${host} skips the palette's ${list(foreign)} colours.`, `Nothing to do; or keep to ${list(profile.colours)} colours.`);
|
|
2425
2502
|
return { ok: !issues.some((i) => i.severity === "error"), issues };
|
|
2426
2503
|
}
|
|
2427
2504
|
function withKeptIssues(check, before) {
|
|
2428
|
-
const had = new Set((_nullishCoalesce(_optionalChain([before, 'optionalAccess',
|
|
2505
|
+
const had = new Set((_nullishCoalesce(_optionalChain([before, 'optionalAccess', _89 => _89.issues]), () => ( []))).filter((i) => i.severity === "error").map((i) => i.facet));
|
|
2429
2506
|
const kept = check.issues.filter((i) => i.severity === "error" && had.has(i.facet));
|
|
2430
2507
|
const issues = check.issues.filter((i) => !kept.includes(i));
|
|
2431
2508
|
return { ok: !issues.some((i) => i.severity === "error"), issues, kept };
|
|
@@ -2458,8 +2535,12 @@ function degrade(brush, profile, options = {}) {
|
|
|
2458
2535
|
delete b.behaviour.surface;
|
|
2459
2536
|
delete b.behaviour.wet;
|
|
2460
2537
|
delete b.behaviour.thick;
|
|
2538
|
+
delete b.livePatterns;
|
|
2461
2539
|
delete b.ghost;
|
|
2462
2540
|
break;
|
|
2541
|
+
case "livePatterns":
|
|
2542
|
+
delete b.livePatterns;
|
|
2543
|
+
break;
|
|
2463
2544
|
case "ghost":
|
|
2464
2545
|
delete b.ghost;
|
|
2465
2546
|
break;
|
|
@@ -2517,7 +2598,7 @@ function degrade(brush, profile, options = {}) {
|
|
|
2517
2598
|
}
|
|
2518
2599
|
dropped.push(issue);
|
|
2519
2600
|
}
|
|
2520
|
-
if (_optionalChain([b, 'access',
|
|
2601
|
+
if (_optionalChain([b, 'access', _90 => _90.behaviour, 'optionalAccess', _91 => _91.exchange]) && !Object.keys(b.behaviour.exchange).length) delete b.behaviour.exchange;
|
|
2521
2602
|
if (b.colour && !Object.keys(b.colour).length) delete b.colour;
|
|
2522
2603
|
const after = checkBrush(b, profile).issues.filter((i) => i.severity === "error");
|
|
2523
2604
|
return { brush: b, dropped, issues: after };
|
|
@@ -2561,7 +2642,7 @@ function parseBrushLibrary2(raw, problems = []) {
|
|
|
2561
2642
|
if (file && file.version !== void 0 && file.version !== 1 && file.version !== 2) {
|
|
2562
2643
|
throw new BrushLibraryError("invalid", `Brush library version ${JSON.stringify(file.version)} is not supported; this library reads versions 1 and 2.`);
|
|
2563
2644
|
}
|
|
2564
|
-
const v1File = _optionalChain([file, 'optionalAccess',
|
|
2645
|
+
const v1File = _optionalChain([file, 'optionalAccess', _92 => _92.version]) === 1;
|
|
2565
2646
|
const out = [];
|
|
2566
2647
|
items.forEach((item, i) => {
|
|
2567
2648
|
const at = `brushes[${i}]`;
|
|
@@ -2822,7 +2903,7 @@ function snapshotBrushLibrary(library, onChange) {
|
|
|
2822
2903
|
(list2) => {
|
|
2823
2904
|
entries = list2;
|
|
2824
2905
|
user = list2.filter((e) => !e.builtin).map((e) => e.brush);
|
|
2825
|
-
_optionalChain([onChange, 'optionalCall',
|
|
2906
|
+
_optionalChain([onChange, 'optionalCall', _93 => _93()]);
|
|
2826
2907
|
},
|
|
2827
2908
|
() => void 0
|
|
2828
2909
|
);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var _chunkQ33V5PEFcjs = require('./chunk-Q33V5PEF.cjs');
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
var _chunkJBZRVLXVcjs = require('./chunk-JBZRVLXV.cjs');
|
|
@@ -44,7 +44,7 @@ function brushPreviewStrength(brush) {
|
|
|
44
44
|
}
|
|
45
45
|
var over = (fg, bg, alpha) => ({ r: fg.r * alpha + bg.r * (1 - alpha), g: fg.g * alpha + bg.g * (1 - alpha), b: fg.b * alpha + bg.b * (1 - alpha), a: 1 });
|
|
46
46
|
function brushPreviewColours(brush, options = {}) {
|
|
47
|
-
const profile = _nullishCoalesce(options.profile, () => (
|
|
47
|
+
const profile = _nullishCoalesce(options.profile, () => ( _chunkQ33V5PEFcjs.PAINT_PROFILE));
|
|
48
48
|
let background = profile.light === "full" && brushPreviewsOnDark(brush) ? BRUSH_PREVIEW_DARK_PAPER : hexOf(_nullishCoalesce(options.paper, () => ( "#ffffff")));
|
|
49
49
|
if (!options.keepPaper && brush.tip.blend === "multiply" && _chunk5UEFBM2Mcjs.relativeLuminance.call(void 0, _chunk5UEFBM2Mcjs.parseColor.call(void 0, background)) < 0.18) background = "#ffffff";
|
|
50
50
|
const bg = _chunk5UEFBM2Mcjs.parseColor.call(void 0, background);
|