@pixerate/editor 0.213.0 → 0.215.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/{chunk-UOGKSVRQ.cjs → chunk-B46UQUDC.cjs} +770 -733
- package/dist/{chunk-W3TOZTL7.js → chunk-F7Z2MKY2.js} +115 -4
- package/dist/{chunk-YBJXCQTR.js → chunk-QXY4YTRI.js} +738 -701
- package/dist/{chunk-H65IBXFI.cjs → chunk-S55JFWDA.cjs} +350 -239
- package/dist/{chunk-QYLWG22N.cjs → chunk-SS53NNZO.cjs} +304 -1
- package/dist/{chunk-LQ5SALHK.js → chunk-U7C655AM.js} +5 -311
- package/dist/{chunk-L52VMQZS.cjs → chunk-UC3PWFM3.cjs} +68 -374
- package/dist/{chunk-L3G23N5Y.js → chunk-ZNA3IQZF.js} +304 -1
- package/dist/image-editor/controller.d.cts +44 -0
- package/dist/image-editor/controller.d.ts +44 -0
- package/dist/image-editor/index.cjs +1768 -1140
- package/dist/image-editor/index.d.cts +1 -0
- package/dist/image-editor/index.d.ts +1 -0
- package/dist/image-editor/index.js +660 -32
- package/dist/image-editor/layers/edge-color.d.cts +27 -0
- package/dist/image-editor/layers/edge-color.d.ts +27 -0
- package/dist/image-editor/layers/serialize.d.cts +13 -0
- package/dist/image-editor/layers/serialize.d.ts +13 -0
- package/dist/image-editor/selection/index.d.cts +1 -0
- package/dist/image-editor/selection/index.d.ts +1 -0
- package/dist/image-editor/selection/inspect.d.cts +70 -0
- package/dist/image-editor/selection/inspect.d.ts +70 -0
- package/dist/image-editor/selection-worker.cjs +4 -4
- package/dist/image-editor/selection-worker.js +2 -2
- package/dist/paint-editor/index.cjs +79 -79
- package/dist/paint-editor/index.js +3 -3
- package/dist/raster/compositor.d.cts +10 -1
- package/dist/raster/compositor.d.ts +10 -1
- package/dist/raster/deep-compositor.d.cts +1 -1
- package/dist/raster/deep-compositor.d.ts +1 -1
- package/dist/raster/index.cjs +4 -2
- package/dist/raster/index.js +3 -1
- package/dist/raster/layers.d.cts +16 -0
- package/dist/raster/layers.d.ts +16 -0
- package/package.json +1 -1
- package/skills/pixerate-image-editor/SKILL.md +9 -6
- package/skills/pixerate-image-editor/references/paths.md +12 -0
- package/skills/pixerate-image-selection-masking/SKILL.md +17 -17
|
@@ -469,63 +469,6 @@ function stableStringify(v) {
|
|
|
469
469
|
return JSON.stringify(v);
|
|
470
470
|
}
|
|
471
471
|
|
|
472
|
-
// src/raster/curve.ts
|
|
473
|
-
var CURVE_LUT_SIZE = 4096;
|
|
474
|
-
var clamp01 = (v) => v <= 0 ? 0 : v >= 1 ? 1 : v;
|
|
475
|
-
function curveLut(points, size = CURVE_LUT_SIZE) {
|
|
476
|
-
const pts = points.filter((p) => Number.isFinite(p.input) && Number.isFinite(p.output)).map((p) => [p.input, p.output]).sort((a, b) => a[0] - b[0]);
|
|
477
|
-
const dedup = [];
|
|
478
|
-
for (const p of pts) {
|
|
479
|
-
if (dedup.length && Math.abs(dedup[dedup.length - 1][0] - p[0]) < 1e-6) continue;
|
|
480
|
-
dedup.push(p);
|
|
481
|
-
}
|
|
482
|
-
const out = new Float32Array(size);
|
|
483
|
-
const n = dedup.length;
|
|
484
|
-
if (n < 2) {
|
|
485
|
-
for (let k = 0; k < size; k++) out[k] = k / (size - 1);
|
|
486
|
-
return out;
|
|
487
|
-
}
|
|
488
|
-
const x = dedup.map((p) => p[0]);
|
|
489
|
-
const y = dedup.map((p) => p[1]);
|
|
490
|
-
const m2 = new Float64Array(n);
|
|
491
|
-
if (n > 2) {
|
|
492
|
-
const c = new Float64Array(n);
|
|
493
|
-
const d = new Float64Array(n);
|
|
494
|
-
for (let i = 1; i < n - 1; i++) {
|
|
495
|
-
const h0 = x[i] - x[i - 1];
|
|
496
|
-
const h1 = x[i + 1] - x[i];
|
|
497
|
-
const a = h0 / 6;
|
|
498
|
-
const b = (h0 + h1) / 3;
|
|
499
|
-
const cc = h1 / 6;
|
|
500
|
-
const r = (y[i + 1] - y[i]) / h1 - (y[i] - y[i - 1]) / h0;
|
|
501
|
-
const denom = b - a * c[i - 1];
|
|
502
|
-
c[i] = cc / denom;
|
|
503
|
-
d[i] = (r - a * d[i - 1]) / denom;
|
|
504
|
-
}
|
|
505
|
-
for (let i = n - 2; i >= 1; i--) m2[i] = d[i] - c[i] * m2[i + 1];
|
|
506
|
-
}
|
|
507
|
-
let seg = 0;
|
|
508
|
-
for (let k = 0; k < size; k++) {
|
|
509
|
-
const xv = k / (size - 1);
|
|
510
|
-
if (xv <= x[0]) {
|
|
511
|
-
out[k] = clamp01(y[0]);
|
|
512
|
-
continue;
|
|
513
|
-
}
|
|
514
|
-
if (xv >= x[n - 1]) {
|
|
515
|
-
out[k] = clamp01(y[n - 1]);
|
|
516
|
-
continue;
|
|
517
|
-
}
|
|
518
|
-
while (seg < n - 2 && xv > x[seg + 1]) seg++;
|
|
519
|
-
const x0 = x[seg], x1 = x[seg + 1];
|
|
520
|
-
const h = x1 - x0;
|
|
521
|
-
const a = (x1 - xv) / h;
|
|
522
|
-
const b = (xv - x0) / h;
|
|
523
|
-
const v = a * y[seg] + b * y[seg + 1] + ((a * a * a - a) * m2[seg] + (b * b * b - b) * m2[seg + 1]) * (h * h) / 6;
|
|
524
|
-
out[k] = clamp01(v);
|
|
525
|
-
}
|
|
526
|
-
return out;
|
|
527
|
-
}
|
|
528
|
-
|
|
529
472
|
// src/raster/effects/patterns.ts
|
|
530
473
|
var PatternTile = class {
|
|
531
474
|
|
|
@@ -655,6 +598,63 @@ function hashNoise(x, y) {
|
|
|
655
598
|
return (h & 65535) / 65536;
|
|
656
599
|
}
|
|
657
600
|
|
|
601
|
+
// src/raster/curve.ts
|
|
602
|
+
var CURVE_LUT_SIZE = 4096;
|
|
603
|
+
var clamp01 = (v) => v <= 0 ? 0 : v >= 1 ? 1 : v;
|
|
604
|
+
function curveLut(points, size = CURVE_LUT_SIZE) {
|
|
605
|
+
const pts = points.filter((p) => Number.isFinite(p.input) && Number.isFinite(p.output)).map((p) => [p.input, p.output]).sort((a, b) => a[0] - b[0]);
|
|
606
|
+
const dedup = [];
|
|
607
|
+
for (const p of pts) {
|
|
608
|
+
if (dedup.length && Math.abs(dedup[dedup.length - 1][0] - p[0]) < 1e-6) continue;
|
|
609
|
+
dedup.push(p);
|
|
610
|
+
}
|
|
611
|
+
const out = new Float32Array(size);
|
|
612
|
+
const n = dedup.length;
|
|
613
|
+
if (n < 2) {
|
|
614
|
+
for (let k = 0; k < size; k++) out[k] = k / (size - 1);
|
|
615
|
+
return out;
|
|
616
|
+
}
|
|
617
|
+
const x = dedup.map((p) => p[0]);
|
|
618
|
+
const y = dedup.map((p) => p[1]);
|
|
619
|
+
const m2 = new Float64Array(n);
|
|
620
|
+
if (n > 2) {
|
|
621
|
+
const c = new Float64Array(n);
|
|
622
|
+
const d = new Float64Array(n);
|
|
623
|
+
for (let i = 1; i < n - 1; i++) {
|
|
624
|
+
const h0 = x[i] - x[i - 1];
|
|
625
|
+
const h1 = x[i + 1] - x[i];
|
|
626
|
+
const a = h0 / 6;
|
|
627
|
+
const b = (h0 + h1) / 3;
|
|
628
|
+
const cc = h1 / 6;
|
|
629
|
+
const r = (y[i + 1] - y[i]) / h1 - (y[i] - y[i - 1]) / h0;
|
|
630
|
+
const denom = b - a * c[i - 1];
|
|
631
|
+
c[i] = cc / denom;
|
|
632
|
+
d[i] = (r - a * d[i - 1]) / denom;
|
|
633
|
+
}
|
|
634
|
+
for (let i = n - 2; i >= 1; i--) m2[i] = d[i] - c[i] * m2[i + 1];
|
|
635
|
+
}
|
|
636
|
+
let seg = 0;
|
|
637
|
+
for (let k = 0; k < size; k++) {
|
|
638
|
+
const xv = k / (size - 1);
|
|
639
|
+
if (xv <= x[0]) {
|
|
640
|
+
out[k] = clamp01(y[0]);
|
|
641
|
+
continue;
|
|
642
|
+
}
|
|
643
|
+
if (xv >= x[n - 1]) {
|
|
644
|
+
out[k] = clamp01(y[n - 1]);
|
|
645
|
+
continue;
|
|
646
|
+
}
|
|
647
|
+
while (seg < n - 2 && xv > x[seg + 1]) seg++;
|
|
648
|
+
const x0 = x[seg], x1 = x[seg + 1];
|
|
649
|
+
const h = x1 - x0;
|
|
650
|
+
const a = (x1 - xv) / h;
|
|
651
|
+
const b = (xv - x0) / h;
|
|
652
|
+
const v = a * y[seg] + b * y[seg + 1] + ((a * a * a - a) * m2[seg] + (b * b * b - b) * m2[seg + 1]) * (h * h) / 6;
|
|
653
|
+
out[k] = clamp01(v);
|
|
654
|
+
}
|
|
655
|
+
return out;
|
|
656
|
+
}
|
|
657
|
+
|
|
658
658
|
// src/raster/effects/render.ts
|
|
659
659
|
var INSIDE_EPS = 0.5 / 255;
|
|
660
660
|
var INF = 1e20;
|
|
@@ -1927,486 +1927,94 @@ function renderLayerEffects(effects, layer, backdrop, canvas, ctx) {
|
|
|
1927
1927
|
});
|
|
1928
1928
|
}
|
|
1929
1929
|
|
|
1930
|
-
// src/raster/
|
|
1931
|
-
var
|
|
1932
|
-
var
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
const acc = new Float32Array(Math.max(0, rect.width * rect.height * 4));
|
|
1950
|
-
if (rect.width > 0 && rect.height > 0) this.runSteps(this.buildSteps(layers), acc, true, rect);
|
|
1951
|
-
return acc;
|
|
1952
|
-
}
|
|
1953
|
-
// --- Steps (as RasterCompositor.buildSteps) ------------------------------------
|
|
1954
|
-
isPixel(l) {
|
|
1955
|
-
return l.type === "pixel" || (_nullishCoalesce(_optionalChain([this, 'access', _2 => _2.profile, 'access', _3 => _3.isPixelLike, 'optionalCall', _4 => _4(l)]), () => ( false)));
|
|
1956
|
-
}
|
|
1957
|
-
isFilter(l) {
|
|
1958
|
-
return _nullishCoalesce(_optionalChain([this, 'access', _5 => _5.profile, 'access', _6 => _6.isFilterLayer, 'optionalCall', _7 => _7(l)]), () => ( false));
|
|
1959
|
-
}
|
|
1960
|
-
buildSteps(layers) {
|
|
1961
|
-
const steps = [];
|
|
1962
|
-
for (const layer of layers) {
|
|
1963
|
-
const last = steps[steps.length - 1];
|
|
1964
|
-
if (layer.clipped && last && (last.kind === "content" || last.kind === "group")) {
|
|
1965
|
-
last.clipped.push(layer);
|
|
1966
|
-
continue;
|
|
1967
|
-
}
|
|
1968
|
-
if (this.isFilter(layer)) {
|
|
1969
|
-
if (last && last.kind === "adjust") last.layers.push(layer);
|
|
1970
|
-
else steps.push({ kind: "adjust", layers: [layer] });
|
|
1971
|
-
} else if (isGroup(layer)) steps.push({ kind: "group", layer, clipped: [], steps: this.buildSteps(_nullishCoalesce(layer.children, () => ( []))) });
|
|
1972
|
-
else steps.push({ kind: "content", layer, clipped: [] });
|
|
1930
|
+
// src/raster/compositor.ts
|
|
1931
|
+
var TILE_PIXELS = _chunk474IQG74cjs.TILE * _chunk474IQG74cjs.TILE;
|
|
1932
|
+
var TILE_BYTES = TILE_PIXELS * 4;
|
|
1933
|
+
function applyEdgeAmbient(content, below, coverage, amount, color2, max) {
|
|
1934
|
+
const k = Math.min(1, Math.max(0, amount));
|
|
1935
|
+
if (!(k > 0)) return;
|
|
1936
|
+
const n = content.length / 4;
|
|
1937
|
+
for (let i = 0; i < n; i++) {
|
|
1938
|
+
const a = content[i * 4 + 3] / max * (coverage ? coverage[i] : 1);
|
|
1939
|
+
if (a <= 0 || a >= 1) continue;
|
|
1940
|
+
let r;
|
|
1941
|
+
let g;
|
|
1942
|
+
let b;
|
|
1943
|
+
if (color2) [r, g, b] = color2;
|
|
1944
|
+
else {
|
|
1945
|
+
if (!(below[i * 4 + 3] > 0)) continue;
|
|
1946
|
+
r = below[i * 4];
|
|
1947
|
+
g = below[i * 4 + 1];
|
|
1948
|
+
b = below[i * 4 + 2];
|
|
1973
1949
|
}
|
|
1974
|
-
|
|
1950
|
+
const t = k * (1 - a);
|
|
1951
|
+
content[i * 4] += t * (r - content[i * 4]);
|
|
1952
|
+
content[i * 4 + 1] += t * (g - content[i * 4 + 1]);
|
|
1953
|
+
content[i * 4 + 2] += t * (b - content[i * 4 + 2]);
|
|
1975
1954
|
}
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1955
|
+
}
|
|
1956
|
+
function sameSig(a, b) {
|
|
1957
|
+
if (!a || a.key !== b.key || a.refs.length !== b.refs.length) return false;
|
|
1958
|
+
for (let i = 0; i < a.refs.length; i++) if (a.refs[i] !== b.refs[i]) return false;
|
|
1959
|
+
return true;
|
|
1960
|
+
}
|
|
1961
|
+
function dirtyInTile(rects, tx, ty) {
|
|
1962
|
+
let x0 = Infinity;
|
|
1963
|
+
let y0 = Infinity;
|
|
1964
|
+
let x1 = -Infinity;
|
|
1965
|
+
let y1 = -Infinity;
|
|
1966
|
+
const ox = tx * _chunk474IQG74cjs.TILE;
|
|
1967
|
+
const oy = ty * _chunk474IQG74cjs.TILE;
|
|
1968
|
+
for (const r of rects) {
|
|
1969
|
+
const a = Math.max(ox, Math.floor(r.x));
|
|
1970
|
+
const b = Math.max(oy, Math.floor(r.y));
|
|
1971
|
+
const c = Math.min(ox + _chunk474IQG74cjs.TILE, Math.ceil(r.x + r.width));
|
|
1972
|
+
const d = Math.min(oy + _chunk474IQG74cjs.TILE, Math.ceil(r.y + r.height));
|
|
1973
|
+
if (c <= a || d <= b) continue;
|
|
1974
|
+
x0 = Math.min(x0, a);
|
|
1975
|
+
y0 = Math.min(y0, b);
|
|
1976
|
+
x1 = Math.max(x1, c);
|
|
1977
|
+
y1 = Math.max(y1, d);
|
|
1979
1978
|
}
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1979
|
+
return x0 === Infinity ? null : { x: x0, y: y0, width: x1 - x0, height: y1 - y0 };
|
|
1980
|
+
}
|
|
1981
|
+
function blendTile(dst, src, mode, alpha, coverage) {
|
|
1982
|
+
if (!(alpha > 0)) return;
|
|
1983
|
+
const normal = mode === "normal";
|
|
1984
|
+
const pigment = mode === "pigment";
|
|
1985
|
+
const lut = !normal && _chunkOLNIPTB3cjs.isSeparableBlendMode.call(void 0, mode) ? separableLut(mode) : null;
|
|
1986
|
+
const cb = [0, 0, 0];
|
|
1987
|
+
const cs = [0, 0, 0];
|
|
1988
|
+
const n = dst.length;
|
|
1989
|
+
for (let i = 0, p = 0; i < n; i += 4, p++) {
|
|
1990
|
+
const sa = src[i + 3];
|
|
1991
|
+
if (sa === 0) continue;
|
|
1992
|
+
const k = coverage ? alpha * coverage[p] : alpha;
|
|
1993
|
+
if (!(k > 0)) continue;
|
|
1994
|
+
if (normal && sa === 255 && k >= 1) {
|
|
1995
|
+
dst[i] = src[i];
|
|
1996
|
+
dst[i + 1] = src[i + 1];
|
|
1997
|
+
dst[i + 2] = src[i + 2];
|
|
1998
|
+
dst[i + 3] = 255;
|
|
1999
|
+
continue;
|
|
1985
2000
|
}
|
|
1986
|
-
const
|
|
1987
|
-
|
|
1988
|
-
const
|
|
1989
|
-
if (
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
if (step.kind === "group" && !this.renderedAlone(layer)) {
|
|
1993
|
-
if (layer.blend === "pass-through" && !clipped.length) {
|
|
1994
|
-
if (layer.opacity >= 1 && !coverage) return this.runSteps(step.steps, acc, empty, r);
|
|
1995
|
-
const before = acc.slice();
|
|
1996
|
-
const stillEmpty = this.runSteps(step.steps, acc, empty, r);
|
|
1997
|
-
lerp(acc, before, layer.opacity, coverage);
|
|
1998
|
-
return empty && stillEmpty;
|
|
1999
|
-
}
|
|
2000
|
-
const buf2 = new Float32Array(acc.length);
|
|
2001
|
-
if (this.runSteps(step.steps, buf2, true, r)) return empty;
|
|
2002
|
-
this.applyClipped(clipped, buf2, r);
|
|
2003
|
-
const mode2 = layer.blend === "pass-through" ? "normal" : layer.blend;
|
|
2004
|
-
this.blend(acc, buf2, mode2, layer.opacity, coverage);
|
|
2005
|
-
return false;
|
|
2001
|
+
const as = sa / 255 * k;
|
|
2002
|
+
const ab = dst[i + 3] / 255;
|
|
2003
|
+
const ao = as + ab * (1 - as);
|
|
2004
|
+
if (ao <= 0) {
|
|
2005
|
+
dst[i] = dst[i + 1] = dst[i + 2] = dst[i + 3] = 0;
|
|
2006
|
+
continue;
|
|
2006
2007
|
}
|
|
2007
|
-
const
|
|
2008
|
-
|
|
2009
|
-
const
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
this.blend(buf, content, "normal", fill2, coverage);
|
|
2018
|
-
this.applyClipped(clipped, buf, r);
|
|
2019
|
-
this.blend(acc, buf, mode, layer.opacity, null);
|
|
2020
|
-
return false;
|
|
2021
|
-
}
|
|
2022
|
-
/**
|
|
2023
|
-
* A pixel layer with effects onto `acc` over `r`: its deep content (filters, mask, clipped
|
|
2024
|
-
* layers) and the effects composited in float. Effect maps come from the 8-bit shape. At 32
|
|
2025
|
-
* bits the effects composite in sRGB-encoded values (their colours and blends are defined
|
|
2026
|
-
* there) and the result is decoded back. Returns whether anything was drawn.
|
|
2027
|
-
*/
|
|
2028
|
-
runEffects(layer, clipped, acc, r, groupSteps = null) {
|
|
2029
|
-
const fx = this.base.effectsInput(layer, r, this.sources);
|
|
2030
|
-
if (!fx) return false;
|
|
2031
|
-
const a = fx.rect;
|
|
2032
|
-
let content;
|
|
2033
|
-
if (groupSteps) {
|
|
2034
|
-
content = new Float32Array(a.width * a.height * 4);
|
|
2035
|
-
this.runSteps(groupSteps, content, true, a);
|
|
2036
|
-
} else content = _nullishCoalesce(this.content(layer, a), () => ( new Float32Array(a.width * a.height * 4)));
|
|
2037
|
-
const coverage = this.base.maskCoverage(layer, a, this.sources);
|
|
2038
|
-
if (coverage) for (let i = 0; i < coverage.length; i++) content[i * 4 + 3] *= coverage[i];
|
|
2039
|
-
if (clipped.length) this.applyClipped(clipped, content, a);
|
|
2040
|
-
const sub = new Float32Array(a.width * a.height * 4);
|
|
2041
|
-
for (let y = 0; y < a.height; y++) {
|
|
2042
|
-
const s = ((a.y - r.y + y) * r.width + (a.x - r.x)) * 4;
|
|
2043
|
-
sub.set(acc.subarray(s, s + a.width * 4), y * a.width * 4);
|
|
2044
|
-
}
|
|
2045
|
-
if (this.linear) {
|
|
2046
|
-
encodeInPlace(sub);
|
|
2047
|
-
encodeInPlace(content);
|
|
2048
|
-
}
|
|
2049
|
-
compositeLayerEffects({ ...fx, backdrop: sub, content });
|
|
2050
|
-
if (this.linear) decodeInPlace(sub);
|
|
2051
|
-
for (let y = 0; y < a.height; y++) acc.set(sub.subarray(y * a.width * 4, (y + 1) * a.width * 4), ((a.y - r.y + y) * r.width + (a.x - r.x)) * 4);
|
|
2052
|
-
return true;
|
|
2053
|
-
}
|
|
2054
|
-
applyClipped(clipped, buf, r) {
|
|
2055
|
-
let run = [];
|
|
2056
|
-
const flush = () => {
|
|
2057
|
-
if (run.length) this.applyFilterRun(run, buf, r);
|
|
2058
|
-
run = [];
|
|
2059
|
-
};
|
|
2060
|
-
for (const c of clipped) {
|
|
2061
|
-
if (this.isFilter(c)) {
|
|
2062
|
-
run.push(c);
|
|
2063
|
-
continue;
|
|
2064
|
-
}
|
|
2065
|
-
flush();
|
|
2066
|
-
const alone = this.renderedAlone(c);
|
|
2067
|
-
const coverage = alone ? null : this.base.maskCoverage(c, r, this.sources);
|
|
2068
|
-
let src;
|
|
2069
|
-
if (isGroup(c) && !alone) {
|
|
2070
|
-
src = new Float32Array(buf.length);
|
|
2071
|
-
if (this.runSteps(this.buildSteps(_nullishCoalesce(c.children, () => ( []))), src, true, r)) continue;
|
|
2072
|
-
} else src = this.content(c, r);
|
|
2073
|
-
if (!src) continue;
|
|
2074
|
-
const fill2 = !alone && this.isPixel(c) ? _nullishCoalesce(c.fillOpacity, () => ( 1)) : 1;
|
|
2075
|
-
const keep = new Float32Array(buf.length >> 2);
|
|
2076
|
-
for (let i = 3, p = 0; i < buf.length; i += 4, p++) keep[p] = buf[i];
|
|
2077
|
-
this.blend(buf, src, c.blend === "pass-through" ? "normal" : this.blendOf(c), c.opacity * fill2, coverage);
|
|
2078
|
-
for (let i = 3, p = 0; i < buf.length; i += 4, p++) buf[i] = keep[p];
|
|
2079
|
-
}
|
|
2080
|
-
flush();
|
|
2081
|
-
}
|
|
2082
|
-
applyFilterRun(layers, acc, r) {
|
|
2083
|
-
const visible = [];
|
|
2084
|
-
let masks;
|
|
2085
|
-
for (const node of layers) {
|
|
2086
|
-
if (!node.visible) continue;
|
|
2087
|
-
const cov = this.base.maskCoverage(node, r, this.sources);
|
|
2088
|
-
if (cov) {
|
|
2089
|
-
if (cov.every((v) => v <= 0)) continue;
|
|
2090
|
-
(masks ??= /* @__PURE__ */ new Map()).set(node.id, cov);
|
|
2091
|
-
}
|
|
2092
|
-
visible.push(node);
|
|
2093
|
-
}
|
|
2094
|
-
if (!visible.length) return;
|
|
2095
|
-
if (this.deep.applyFilterRunDeep) {
|
|
2096
|
-
if (this.linear) mapColour(acc, _chunkOLNIPTB3cjs.srgbEncode);
|
|
2097
|
-
this.deep.applyFilterRunDeep(visible, acc, r, masks, this.sources);
|
|
2098
|
-
if (this.linear) mapColour(acc, _chunkOLNIPTB3cjs.srgbDecode);
|
|
2099
|
-
return;
|
|
2100
|
-
}
|
|
2101
|
-
const bytes = this.to8(acc);
|
|
2102
|
-
_optionalChain([this, 'access', _8 => _8.profile, 'access', _9 => _9.applyFilterRun, 'optionalCall', _10 => _10(visible, bytes, r, masks, this.sources)]);
|
|
2103
|
-
acc.set(this.from8(bytes));
|
|
2104
|
-
}
|
|
2105
|
-
// --- Layer content ---------------------------------------------------------------
|
|
2106
|
-
/** Layers drawn by the 8-bit compositor alone (effects, pixel filters, content the editor draws). */
|
|
2107
|
-
/** A pixel(-like) layer or a group with effects: composited in float through `compositeLayerEffects`. */
|
|
2108
|
-
deepEffects(layer) {
|
|
2109
|
-
return hasActiveEffects(layer.effects) && !this.isFilter(layer) && (isGroup(layer) || this.isPixel(layer));
|
|
2110
|
-
}
|
|
2111
|
-
renderedAlone(layer) {
|
|
2112
|
-
if (hasActiveEffects(layer.effects) && !this.isFilter(layer) && !this.deepEffects(layer)) return true;
|
|
2113
|
-
if (this.isPixel(layer)) return Boolean(_optionalChain([this, 'access', _11 => _11.profile, 'access', _12 => _12.pixelFilters, 'optionalCall', _13 => _13(layer)])) && !_optionalChain([this, 'access', _14 => _14.deep, 'access', _15 => _15.pixelFiltersDeep, 'optionalCall', _16 => _16(layer)]);
|
|
2114
|
-
return !isGroup(layer);
|
|
2115
|
-
}
|
|
2116
|
-
blendOf(layer) {
|
|
2117
|
-
return _nullishCoalesce(_optionalChain([this, 'access', _17 => _17.profile, 'access', _18 => _18.contentBlend, 'optionalCall', _19 => _19(layer)]), () => ( layer.blend));
|
|
2118
|
-
}
|
|
2119
|
-
/** A layer's float RGBA over `r` (straight alpha, working space), or `null` when it has none there. */
|
|
2120
|
-
content(layer, r) {
|
|
2121
|
-
if (this.renderedAlone(layer)) {
|
|
2122
|
-
const solo = { ...layer, blend: isGroup(layer) && layer.blend === "pass-through" ? "pass-through" : "normal", opacity: 1, clipped: false };
|
|
2123
|
-
const bytes = this.base.composite([solo], r, this.sources);
|
|
2124
|
-
return this.from8(bytes);
|
|
2125
|
-
}
|
|
2126
|
-
const surface = this.sources.surfaceOf ? this.sources.surfaceOf(layer) : layer.surface;
|
|
2127
|
-
if (!surface) return null;
|
|
2128
|
-
const ox = _nullishCoalesce(_optionalChain([layer, 'access', _20 => _20.offset, 'optionalAccess', _21 => _21.x]), () => ( 0));
|
|
2129
|
-
const oy = _nullishCoalesce(_optionalChain([layer, 'access', _22 => _22.offset, 'optionalAccess', _23 => _23.y]), () => ( 0));
|
|
2130
|
-
const filters = this.isPixel(layer) ? _nullishCoalesce(_optionalChain([this, 'access', _24 => _24.deep, 'access', _25 => _25.pixelFiltersDeep, 'optionalCall', _26 => _26(layer)]), () => ( null)) : null;
|
|
2131
|
-
if (!filters) return this.samples(surface, { x: r.x - ox, y: r.y - oy, width: r.width, height: r.height });
|
|
2132
|
-
const m = filters.reach;
|
|
2133
|
-
const W = this.sources.width;
|
|
2134
|
-
const H = this.sources.height;
|
|
2135
|
-
const x0 = m ? Math.max(0, r.x - m) : r.x;
|
|
2136
|
-
const y0 = m ? Math.max(0, r.y - m) : r.y;
|
|
2137
|
-
const x1 = m ? Math.min(W, r.x + r.width + m) : r.x + r.width;
|
|
2138
|
-
const y1 = m ? Math.min(H, r.y + r.height + m) : r.y + r.height;
|
|
2139
|
-
if (x1 <= x0 || y1 <= y0) return new Float32Array(r.width * r.height * 4);
|
|
2140
|
-
const big = { x: x0, y: y0, width: x1 - x0, height: y1 - y0 };
|
|
2141
|
-
const data = this.samples(surface, { ...big, x: big.x - ox, y: big.y - oy });
|
|
2142
|
-
filters.apply(data, big.width, big.height, this.linear);
|
|
2143
|
-
if (big.x === r.x && big.y === r.y && big.width === r.width && big.height === r.height) return data;
|
|
2144
|
-
const out = new Float32Array(r.width * r.height * 4);
|
|
2145
|
-
for (let y = 0; y < r.height; y++) {
|
|
2146
|
-
const sy = r.y + y - big.y;
|
|
2147
|
-
if (sy < 0 || sy >= big.height) continue;
|
|
2148
|
-
for (let x = 0; x < r.width; x++) {
|
|
2149
|
-
const sx = r.x + x - big.x;
|
|
2150
|
-
if (sx < 0 || sx >= big.width) continue;
|
|
2151
|
-
const s = (sy * big.width + sx) * 4;
|
|
2152
|
-
const d = (y * r.width + x) * 4;
|
|
2153
|
-
out[d] = data[s];
|
|
2154
|
-
out[d + 1] = data[s + 1];
|
|
2155
|
-
out[d + 2] = data[s + 2];
|
|
2156
|
-
out[d + 3] = data[s + 3];
|
|
2157
|
-
}
|
|
2158
|
-
}
|
|
2159
|
-
return out;
|
|
2160
|
-
}
|
|
2161
|
-
/** A surface's samples over `rect` (layer space) in the working space. */
|
|
2162
|
-
samples(surface, rect) {
|
|
2163
|
-
const samples = _chunkOLNIPTB3cjs.readDeepRegion.call(void 0, surface, rect, this.depth);
|
|
2164
|
-
if (samples instanceof Float32Array) return samples;
|
|
2165
|
-
const out = new Float32Array(samples.length);
|
|
2166
|
-
for (let i = 0; i < samples.length; i++) out[i] = samples[i] / 65535;
|
|
2167
|
-
return out;
|
|
2168
|
-
}
|
|
2169
|
-
/** 8-bit RGBA to the working space. */
|
|
2170
|
-
from8(bytes) {
|
|
2171
|
-
if (this.linear) return _chunkOLNIPTB3cjs.to32From8.call(void 0, bytes, 4);
|
|
2172
|
-
const out = new Float32Array(bytes.length);
|
|
2173
|
-
for (let i = 0; i < bytes.length; i++) out[i] = bytes[i] / 255;
|
|
2174
|
-
return out;
|
|
2175
|
-
}
|
|
2176
|
-
/** The working space to 8-bit RGBA. */
|
|
2177
|
-
to8(acc) {
|
|
2178
|
-
const out = new Uint8ClampedArray(acc.length);
|
|
2179
|
-
for (let i = 0; i < acc.length; i += 4) {
|
|
2180
|
-
for (let c = 0; c < 3; c++) out[i + c] = Math.round((this.linear ? _chunkOLNIPTB3cjs.srgbEncode.call(void 0, acc[i + c]) : acc[i + c]) * 255);
|
|
2181
|
-
out[i + 3] = Math.round(acc[i + 3] * 255);
|
|
2182
|
-
}
|
|
2183
|
-
return out;
|
|
2184
|
-
}
|
|
2185
|
-
// --- Blending --------------------------------------------------------------------
|
|
2186
|
-
/** `src` over `dst` with `mode` at `alpha` × coverage (straight alpha, float), as `blendTile`. */
|
|
2187
|
-
blend(dst, src, mode, alpha, coverage) {
|
|
2188
|
-
if (!(alpha > 0)) return;
|
|
2189
|
-
const normal = mode === "normal";
|
|
2190
|
-
const pigment = mode === "pigment";
|
|
2191
|
-
const cb = [0, 0, 0];
|
|
2192
|
-
const cs = [0, 0, 0];
|
|
2193
|
-
const mix = [0, 0, 0];
|
|
2194
|
-
for (let i = 0, p = 0; i < dst.length; i += 4, p++) {
|
|
2195
|
-
const sa = src[i + 3];
|
|
2196
|
-
if (!(sa > 0)) continue;
|
|
2197
|
-
const k = coverage ? alpha * coverage[p] : alpha;
|
|
2198
|
-
if (!(k > 0)) continue;
|
|
2199
|
-
const as = Math.min(1, sa * k);
|
|
2200
|
-
const ab = dst[i + 3];
|
|
2201
|
-
const ao = as + ab * (1 - as);
|
|
2202
|
-
if (ao <= 0) {
|
|
2203
|
-
dst[i] = dst[i + 1] = dst[i + 2] = dst[i + 3] = 0;
|
|
2204
|
-
continue;
|
|
2205
|
-
}
|
|
2206
|
-
if (normal && as >= 1) {
|
|
2207
|
-
dst[i] = src[i];
|
|
2208
|
-
dst[i + 1] = src[i + 1];
|
|
2209
|
-
dst[i + 2] = src[i + 2];
|
|
2210
|
-
dst[i + 3] = 1;
|
|
2211
|
-
continue;
|
|
2212
|
-
}
|
|
2213
|
-
for (let c = 0; c < 3; c++) {
|
|
2214
|
-
cb[c] = dst[i + c];
|
|
2215
|
-
cs[c] = src[i + c];
|
|
2216
|
-
}
|
|
2217
|
-
if (pigment) {
|
|
2218
|
-
if (this.linear) for (let c = 0; c < 3; c++) cb[c] = _chunkOLNIPTB3cjs.srgbEncode.call(void 0, cb[c]), cs[c] = _chunkOLNIPTB3cjs.srgbEncode.call(void 0, cs[c]);
|
|
2219
|
-
_chunkOLNIPTB3cjs.mixPigmentRgb.call(void 0, cb, cs, as / ao, mix);
|
|
2220
|
-
for (let c = 0; c < 3; c++) dst[i + c] = this.linear ? _chunkOLNIPTB3cjs.srgbDecode.call(void 0, mix[c]) : mix[c];
|
|
2221
|
-
dst[i + 3] = ao;
|
|
2222
|
-
continue;
|
|
2223
|
-
}
|
|
2224
|
-
const m = normal ? cs : _chunkOLNIPTB3cjs.blendRgb.call(void 0, mode, cb, cs);
|
|
2225
|
-
const wb = (1 - as) * ab;
|
|
2226
|
-
const ws = (1 - ab) * as;
|
|
2227
|
-
const wm = as * ab;
|
|
2228
|
-
for (let c = 0; c < 3; c++) dst[i + c] = (wb * cb[c] + ws * cs[c] + wm * m[c]) / ao;
|
|
2229
|
-
dst[i + 3] = ao;
|
|
2230
|
-
}
|
|
2231
|
-
}
|
|
2232
|
-
};
|
|
2233
|
-
function lerp(dst, before, alpha, coverage) {
|
|
2234
|
-
for (let i = 0, p = 0; i < dst.length; i += 4, p++) {
|
|
2235
|
-
const k = coverage ? alpha * coverage[p] : alpha;
|
|
2236
|
-
if (k >= 1) continue;
|
|
2237
|
-
for (let c = 0; c < 4; c++) dst[i + c] = before[i + c] + (dst[i + c] - before[i + c]) * k;
|
|
2238
|
-
}
|
|
2239
|
-
}
|
|
2240
|
-
function mapColour(data, f) {
|
|
2241
|
-
for (let i = 0; i < data.length; i += 4) {
|
|
2242
|
-
data[i] = f(data[i]);
|
|
2243
|
-
data[i + 1] = f(data[i + 1]);
|
|
2244
|
-
data[i + 2] = f(data[i + 2]);
|
|
2245
|
-
}
|
|
2246
|
-
}
|
|
2247
|
-
function workingToSamples(data, depth) {
|
|
2248
|
-
if (depth === 32) return data;
|
|
2249
|
-
const out = new Uint16Array(data.length);
|
|
2250
|
-
for (let i = 0; i < data.length; i++) {
|
|
2251
|
-
const v = data[i];
|
|
2252
|
-
out[i] = v > 0 ? v < 1 ? Math.round(v * 65535) : 65535 : 0;
|
|
2253
|
-
}
|
|
2254
|
-
return out;
|
|
2255
|
-
}
|
|
2256
|
-
function encodeInPlace(d) {
|
|
2257
|
-
for (let i = 0; i < d.length; i += 4) {
|
|
2258
|
-
d[i] = _chunkOLNIPTB3cjs.srgbEncode.call(void 0, d[i]);
|
|
2259
|
-
d[i + 1] = _chunkOLNIPTB3cjs.srgbEncode.call(void 0, d[i + 1]);
|
|
2260
|
-
d[i + 2] = _chunkOLNIPTB3cjs.srgbEncode.call(void 0, d[i + 2]);
|
|
2261
|
-
}
|
|
2262
|
-
}
|
|
2263
|
-
function decodeInPlace(d) {
|
|
2264
|
-
for (let i = 0; i < d.length; i += 4) {
|
|
2265
|
-
d[i] = _chunkOLNIPTB3cjs.srgbDecode.call(void 0, d[i]);
|
|
2266
|
-
d[i + 1] = _chunkOLNIPTB3cjs.srgbDecode.call(void 0, d[i + 1]);
|
|
2267
|
-
d[i + 2] = _chunkOLNIPTB3cjs.srgbDecode.call(void 0, d[i + 2]);
|
|
2268
|
-
}
|
|
2269
|
-
}
|
|
2270
|
-
|
|
2271
|
-
// src/raster/layers.ts
|
|
2272
|
-
var childrenOf = (l) => l.type === "group" ? _nullishCoalesce(l.children, () => ( null)) : null;
|
|
2273
|
-
function flattenLayers(layers) {
|
|
2274
|
-
const out = [];
|
|
2275
|
-
const walk = (list) => {
|
|
2276
|
-
for (const l of list) {
|
|
2277
|
-
out.push(l);
|
|
2278
|
-
const c = childrenOf(l);
|
|
2279
|
-
if (c) walk(c);
|
|
2280
|
-
}
|
|
2281
|
-
};
|
|
2282
|
-
walk(layers);
|
|
2283
|
-
return out;
|
|
2284
|
-
}
|
|
2285
|
-
function findLayer(layers, id) {
|
|
2286
|
-
const walk = (list, parent, path) => {
|
|
2287
|
-
for (let i = 0; i < list.length; i++) {
|
|
2288
|
-
const l = list[i];
|
|
2289
|
-
if (l.id === id) return { layer: l, parent, index: i, path };
|
|
2290
|
-
const c = childrenOf(l);
|
|
2291
|
-
if (c) {
|
|
2292
|
-
const g = l;
|
|
2293
|
-
const hit = walk(c, g, [...path, g]);
|
|
2294
|
-
if (hit) return hit;
|
|
2295
|
-
}
|
|
2296
|
-
}
|
|
2297
|
-
return null;
|
|
2298
|
-
};
|
|
2299
|
-
return walk(layers, null, []);
|
|
2300
|
-
}
|
|
2301
|
-
function mapLayer(layers, id, fn) {
|
|
2302
|
-
let changed = false;
|
|
2303
|
-
const walk = (list) => {
|
|
2304
|
-
let out = null;
|
|
2305
|
-
for (let i = 0; i < list.length; i++) {
|
|
2306
|
-
const l = list[i];
|
|
2307
|
-
let next = l;
|
|
2308
|
-
if (l.id === id) {
|
|
2309
|
-
next = fn(l);
|
|
2310
|
-
changed = true;
|
|
2311
|
-
} else {
|
|
2312
|
-
const c = childrenOf(l);
|
|
2313
|
-
if (c) {
|
|
2314
|
-
const children = walk(c);
|
|
2315
|
-
if (children !== c) next = { ...l, children };
|
|
2316
|
-
}
|
|
2317
|
-
}
|
|
2318
|
-
if (next !== l) {
|
|
2319
|
-
if (!out) out = list.slice(0, i);
|
|
2320
|
-
if (next) out.push(next);
|
|
2321
|
-
} else if (out) out.push(l);
|
|
2322
|
-
}
|
|
2323
|
-
return _nullishCoalesce(out, () => ( list));
|
|
2324
|
-
};
|
|
2325
|
-
const result = walk(layers);
|
|
2326
|
-
return changed ? result : layers;
|
|
2327
|
-
}
|
|
2328
|
-
function insertLayer(layers, layer, parentId, index) {
|
|
2329
|
-
const put = (list) => {
|
|
2330
|
-
const at = index === void 0 ? list.length : Math.max(0, Math.min(list.length, index));
|
|
2331
|
-
const next = list.slice();
|
|
2332
|
-
next.splice(at, 0, layer);
|
|
2333
|
-
return next;
|
|
2334
|
-
};
|
|
2335
|
-
if (!parentId) return put(layers);
|
|
2336
|
-
return mapLayer(layers, parentId, (g) => {
|
|
2337
|
-
const c = childrenOf(g);
|
|
2338
|
-
return c ? { ...g, children: put(c) } : g;
|
|
2339
|
-
});
|
|
2340
|
-
}
|
|
2341
|
-
function isLayerLocked(layer, what) {
|
|
2342
|
-
return Boolean(_optionalChain([layer, 'access', _27 => _27.locks, 'optionalAccess', _28 => _28.all]) || _optionalChain([layer, 'access', _29 => _29.locks, 'optionalAccess', _30 => _30[what]]));
|
|
2343
|
-
}
|
|
2344
|
-
|
|
2345
|
-
// src/raster/compositor.ts
|
|
2346
|
-
var TILE_PIXELS = _chunk474IQG74cjs.TILE * _chunk474IQG74cjs.TILE;
|
|
2347
|
-
var TILE_BYTES = TILE_PIXELS * 4;
|
|
2348
|
-
function sameSig(a, b) {
|
|
2349
|
-
if (!a || a.key !== b.key || a.refs.length !== b.refs.length) return false;
|
|
2350
|
-
for (let i = 0; i < a.refs.length; i++) if (a.refs[i] !== b.refs[i]) return false;
|
|
2351
|
-
return true;
|
|
2352
|
-
}
|
|
2353
|
-
function dirtyInTile(rects, tx, ty) {
|
|
2354
|
-
let x0 = Infinity;
|
|
2355
|
-
let y0 = Infinity;
|
|
2356
|
-
let x1 = -Infinity;
|
|
2357
|
-
let y1 = -Infinity;
|
|
2358
|
-
const ox = tx * _chunk474IQG74cjs.TILE;
|
|
2359
|
-
const oy = ty * _chunk474IQG74cjs.TILE;
|
|
2360
|
-
for (const r of rects) {
|
|
2361
|
-
const a = Math.max(ox, Math.floor(r.x));
|
|
2362
|
-
const b = Math.max(oy, Math.floor(r.y));
|
|
2363
|
-
const c = Math.min(ox + _chunk474IQG74cjs.TILE, Math.ceil(r.x + r.width));
|
|
2364
|
-
const d = Math.min(oy + _chunk474IQG74cjs.TILE, Math.ceil(r.y + r.height));
|
|
2365
|
-
if (c <= a || d <= b) continue;
|
|
2366
|
-
x0 = Math.min(x0, a);
|
|
2367
|
-
y0 = Math.min(y0, b);
|
|
2368
|
-
x1 = Math.max(x1, c);
|
|
2369
|
-
y1 = Math.max(y1, d);
|
|
2370
|
-
}
|
|
2371
|
-
return x0 === Infinity ? null : { x: x0, y: y0, width: x1 - x0, height: y1 - y0 };
|
|
2372
|
-
}
|
|
2373
|
-
function blendTile(dst, src, mode, alpha, coverage) {
|
|
2374
|
-
if (!(alpha > 0)) return;
|
|
2375
|
-
const normal = mode === "normal";
|
|
2376
|
-
const pigment = mode === "pigment";
|
|
2377
|
-
const lut = !normal && _chunkOLNIPTB3cjs.isSeparableBlendMode.call(void 0, mode) ? separableLut(mode) : null;
|
|
2378
|
-
const cb = [0, 0, 0];
|
|
2379
|
-
const cs = [0, 0, 0];
|
|
2380
|
-
const n = dst.length;
|
|
2381
|
-
for (let i = 0, p = 0; i < n; i += 4, p++) {
|
|
2382
|
-
const sa = src[i + 3];
|
|
2383
|
-
if (sa === 0) continue;
|
|
2384
|
-
const k = coverage ? alpha * coverage[p] : alpha;
|
|
2385
|
-
if (!(k > 0)) continue;
|
|
2386
|
-
if (normal && sa === 255 && k >= 1) {
|
|
2387
|
-
dst[i] = src[i];
|
|
2388
|
-
dst[i + 1] = src[i + 1];
|
|
2389
|
-
dst[i + 2] = src[i + 2];
|
|
2390
|
-
dst[i + 3] = 255;
|
|
2391
|
-
continue;
|
|
2392
|
-
}
|
|
2393
|
-
const as = sa / 255 * k;
|
|
2394
|
-
const ab = dst[i + 3] / 255;
|
|
2395
|
-
const ao = as + ab * (1 - as);
|
|
2396
|
-
if (ao <= 0) {
|
|
2397
|
-
dst[i] = dst[i + 1] = dst[i + 2] = dst[i + 3] = 0;
|
|
2398
|
-
continue;
|
|
2399
|
-
}
|
|
2400
|
-
const d0 = dst[i];
|
|
2401
|
-
const d1 = dst[i + 1];
|
|
2402
|
-
const d2 = dst[i + 2];
|
|
2403
|
-
if (pigment) {
|
|
2404
|
-
_chunkOLNIPTB3cjs.mixPigment8.call(void 0, d0, d1, d2, src[i], src[i + 1], src[i + 2], as / ao, cb);
|
|
2405
|
-
dst[i] = Math.round(cb[0] * 255);
|
|
2406
|
-
dst[i + 1] = Math.round(cb[1] * 255);
|
|
2407
|
-
dst[i + 2] = Math.round(cb[2] * 255);
|
|
2408
|
-
dst[i + 3] = Math.round(ao * 255);
|
|
2409
|
-
continue;
|
|
2008
|
+
const d0 = dst[i];
|
|
2009
|
+
const d1 = dst[i + 1];
|
|
2010
|
+
const d2 = dst[i + 2];
|
|
2011
|
+
if (pigment) {
|
|
2012
|
+
_chunkOLNIPTB3cjs.mixPigment8.call(void 0, d0, d1, d2, src[i], src[i + 1], src[i + 2], as / ao, cb);
|
|
2013
|
+
dst[i] = Math.round(cb[0] * 255);
|
|
2014
|
+
dst[i + 1] = Math.round(cb[1] * 255);
|
|
2015
|
+
dst[i + 2] = Math.round(cb[2] * 255);
|
|
2016
|
+
dst[i + 3] = Math.round(ao * 255);
|
|
2017
|
+
continue;
|
|
2410
2018
|
}
|
|
2411
2019
|
const b0 = d0 / 255;
|
|
2412
2020
|
const b1 = d1 / 255;
|
|
@@ -2470,7 +2078,7 @@ function lerpTile(dst, before, alpha, coverage) {
|
|
|
2470
2078
|
}
|
|
2471
2079
|
}
|
|
2472
2080
|
var ZERO_TILE = new Uint8ClampedArray(TILE_BYTES);
|
|
2473
|
-
var
|
|
2081
|
+
var isGroup = (l) => l.type === "group";
|
|
2474
2082
|
var maskDepths = /* @__PURE__ */ new WeakMap();
|
|
2475
2083
|
function maskDepth(surface) {
|
|
2476
2084
|
let d = maskDepths.get(surface);
|
|
@@ -2562,7 +2170,7 @@ var RasterCompositor = (_class = class {
|
|
|
2562
2170
|
const dirty = grow > 0 ? options.dirty.map((d) => inflateRect(d, grow)) : options.dirty;
|
|
2563
2171
|
for (const { tx, ty } of _chunk474IQG74cjs.tilesInRect.call(void 0, rect)) {
|
|
2564
2172
|
stats.tiles++;
|
|
2565
|
-
const before = _optionalChain([this, 'access',
|
|
2173
|
+
const before = _optionalChain([this, 'access', _2 => _2.tiles, 'access', _3 => _3.get, 'call', _4 => _4(_chunk474IQG74cjs.tileKey.call(void 0, tx, ty)), 'optionalAccess', _5 => _5.result]);
|
|
2566
2174
|
const data = this.compositeTile(layers, steps, tx, ty, stats, dirty ? dirtyInTile(dirty, tx, ty) : null);
|
|
2567
2175
|
onTile(tx, ty, data, data !== before);
|
|
2568
2176
|
}
|
|
@@ -2603,7 +2211,7 @@ var RasterCompositor = (_class = class {
|
|
|
2603
2211
|
return {
|
|
2604
2212
|
rect,
|
|
2605
2213
|
maps,
|
|
2606
|
-
blend:
|
|
2214
|
+
blend: isGroup(layer) ? layer.blend === "pass-through" ? "normal" : layer.blend : this.contentBlend(layer),
|
|
2607
2215
|
opacity: layer.opacity,
|
|
2608
2216
|
fillOpacity: this.isPixel(layer) ? _nullishCoalesce(layer.fillOpacity, () => ( 1)) : 1,
|
|
2609
2217
|
canvas: { x: 0, y: 0, width: this.sources.width, height: this.sources.height },
|
|
@@ -2613,10 +2221,10 @@ var RasterCompositor = (_class = class {
|
|
|
2613
2221
|
// --- Steps -------------------------------------------------------------------
|
|
2614
2222
|
/** Pixel layers, and the layer kinds the profile composites like them. */
|
|
2615
2223
|
isPixel(l) {
|
|
2616
|
-
return l.type === "pixel" || (_nullishCoalesce(_optionalChain([this, 'access',
|
|
2224
|
+
return l.type === "pixel" || (_nullishCoalesce(_optionalChain([this, 'access', _6 => _6.profile, 'access', _7 => _7.isPixelLike, 'optionalCall', _8 => _8(l)]), () => ( false)));
|
|
2617
2225
|
}
|
|
2618
2226
|
isFilter(l) {
|
|
2619
|
-
return _nullishCoalesce(_optionalChain([this, 'access',
|
|
2227
|
+
return _nullishCoalesce(_optionalChain([this, 'access', _9 => _9.profile, 'access', _10 => _10.isFilterLayer, 'optionalCall', _11 => _11(l)]), () => ( false));
|
|
2620
2228
|
}
|
|
2621
2229
|
/**
|
|
2622
2230
|
* Groups a layer list into compositing steps: clipped layers join the nearest unclipped
|
|
@@ -2635,7 +2243,7 @@ var RasterCompositor = (_class = class {
|
|
|
2635
2243
|
if (this.isFilter(layer)) {
|
|
2636
2244
|
if (last && last.kind === "adjust") last.layers.push(layer);
|
|
2637
2245
|
else steps.push({ kind: "adjust", layers: [layer] });
|
|
2638
|
-
} else if (
|
|
2246
|
+
} else if (isGroup(layer)) {
|
|
2639
2247
|
steps.push({ kind: "group", layer, clipped: [], steps: this.buildSteps(_nullishCoalesce(layer.children, () => ( []))) });
|
|
2640
2248
|
} else {
|
|
2641
2249
|
steps.push({ kind: "content", layer, clipped: [] });
|
|
@@ -2646,7 +2254,7 @@ var RasterCompositor = (_class = class {
|
|
|
2646
2254
|
}
|
|
2647
2255
|
/** The index of the top-level step that holds layer `id` (searching groups and clipped layers), or -1. */
|
|
2648
2256
|
stepIndexOf(steps, id) {
|
|
2649
|
-
const holds = (l) => l.id === id ||
|
|
2257
|
+
const holds = (l) => l.id === id || isGroup(l) && (_nullishCoalesce(l.children, () => ( []))).some(holds);
|
|
2650
2258
|
return steps.findIndex((s) => s.kind === "adjust" ? s.layers.some(holds) : holds(s.layer) || s.clipped.some(holds));
|
|
2651
2259
|
}
|
|
2652
2260
|
/** Properties of a layer that change pixels, minus its surfaces (memoised per object). */
|
|
@@ -2655,9 +2263,10 @@ var RasterCompositor = (_class = class {
|
|
|
2655
2263
|
if (key !== void 0) return key;
|
|
2656
2264
|
const mask = layer.mask ? [layer.mask.enabled !== false, _nullishCoalesce(layer.mask.density, () => ( 1)), _nullishCoalesce(layer.mask.feather, () => ( 0)), layer.mask.defaultValue, _nullishCoalesce(layer.mask.source, () => ( null))] : null;
|
|
2657
2265
|
const base = [layer.type, layer.id, layer.visible, layer.opacity, layer.blend, Boolean(layer.clipped), mask];
|
|
2658
|
-
if (this.isPixel(layer)) base.push(_nullishCoalesce(_optionalChain([layer, 'access',
|
|
2266
|
+
if (this.isPixel(layer)) base.push(_nullishCoalesce(_optionalChain([layer, 'access', _12 => _12.offset, 'optionalAccess', _13 => _13.x]), () => ( 0)), _nullishCoalesce(_optionalChain([layer, 'access', _14 => _14.offset, 'optionalAccess', _15 => _15.y]), () => ( 0)), _nullishCoalesce(layer.fillOpacity, () => ( 1)));
|
|
2659
2267
|
if (this.hasEffects(layer)) base.push(effectsFingerprint(layer.effects));
|
|
2660
|
-
|
|
2268
|
+
if (layer.edge) base.push(layer.edge);
|
|
2269
|
+
const extra = _optionalChain([this, 'access', _16 => _16.profile, 'access', _17 => _17.layerKey, 'optionalCall', _18 => _18(layer)]);
|
|
2661
2270
|
if (extra !== void 0) base.push(extra);
|
|
2662
2271
|
key = JSON.stringify(base);
|
|
2663
2272
|
this.propsKeyCache.set(layer, key);
|
|
@@ -2794,7 +2403,7 @@ var RasterCompositor = (_class = class {
|
|
|
2794
2403
|
}
|
|
2795
2404
|
layerSig(layer, tx, ty) {
|
|
2796
2405
|
if (this.isFilter(layer)) return { key: this.propsKey(layer), refs: this.maskRefs(layer, tx, ty, 0, 0) };
|
|
2797
|
-
if (
|
|
2406
|
+
if (isGroup(layer)) return this.groupSig(layer, this.buildSteps(_nullishCoalesce(layer.children, () => ( []))), tx, ty);
|
|
2798
2407
|
return this.contentSig(layer, tx, ty);
|
|
2799
2408
|
}
|
|
2800
2409
|
groupSig(group, steps, tx, ty) {
|
|
@@ -2824,7 +2433,7 @@ var RasterCompositor = (_class = class {
|
|
|
2824
2433
|
const refs = [surface.defaultValue];
|
|
2825
2434
|
const r = { x: tx * _chunk474IQG74cjs.TILE - dx, y: ty * _chunk474IQG74cjs.TILE - dy, width: _chunk474IQG74cjs.TILE, height: _chunk474IQG74cjs.TILE };
|
|
2826
2435
|
for (const t of _chunk474IQG74cjs.tilesInRect.call(void 0, r)) refs.push(_nullishCoalesce(surface.getTile(t.tx, t.ty), () => ( null)));
|
|
2827
|
-
refs.push(...this.maskRefs(layer, tx, ty, _nullishCoalesce(_optionalChain([layer, 'access',
|
|
2436
|
+
refs.push(...this.maskRefs(layer, tx, ty, _nullishCoalesce(_optionalChain([layer, 'access', _19 => _19.offset, 'optionalAccess', _20 => _20.x]), () => ( 0)), _nullishCoalesce(_optionalChain([layer, 'access', _21 => _21.offset, 'optionalAccess', _22 => _22.y]), () => ( 0))));
|
|
2828
2437
|
return { key, refs };
|
|
2829
2438
|
}
|
|
2830
2439
|
// --- Layer effects ------------------------------------------------------------
|
|
@@ -2854,7 +2463,7 @@ var RasterCompositor = (_class = class {
|
|
|
2854
2463
|
this.fxContext = {
|
|
2855
2464
|
light: _nullishCoalesce(sources.globalLight, () => ( DEFAULT_GLOBAL_LIGHT)),
|
|
2856
2465
|
pattern: (id) => {
|
|
2857
|
-
const p = _nullishCoalesce(_optionalChain([sources, 'access',
|
|
2466
|
+
const p = _nullishCoalesce(_optionalChain([sources, 'access', _23 => _23.pattern, 'optionalCall', _24 => _24(id)]), () => ( builtinPattern(id)));
|
|
2858
2467
|
if (!p || !(p.width > 0 && p.height > 0) || p.data.length < p.width * p.height * 4) return null;
|
|
2859
2468
|
let t = tiles.get(p);
|
|
2860
2469
|
if (!t) {
|
|
@@ -2884,7 +2493,7 @@ var RasterCompositor = (_class = class {
|
|
|
2884
2493
|
shapeSigs(layer, region) {
|
|
2885
2494
|
const sigs = /* @__PURE__ */ new Map();
|
|
2886
2495
|
if (region.width <= 0 || region.height <= 0) return sigs;
|
|
2887
|
-
const steps =
|
|
2496
|
+
const steps = isGroup(layer) ? this.buildSteps(_nullishCoalesce(layer.children, () => ( []))) : null;
|
|
2888
2497
|
for (const t of _chunk474IQG74cjs.tilesInRect.call(void 0, region)) {
|
|
2889
2498
|
sigs.set(_chunk474IQG74cjs.tileKey.call(void 0, t.tx, t.ty), steps ? this.plainGroupSig(layer, steps, t.tx, t.ty) : this.plainContentSig(layer, t.tx, t.ty));
|
|
2890
2499
|
}
|
|
@@ -2906,7 +2515,7 @@ var RasterCompositor = (_class = class {
|
|
|
2906
2515
|
* laid out over the layer's bounds.
|
|
2907
2516
|
*/
|
|
2908
2517
|
effectSig(layer, tx, ty) {
|
|
2909
|
-
const key = (
|
|
2518
|
+
const key = (isGroup(layer) ? "Gfx" : "Cfx") + this.propsKey(layer) + this.lightKey();
|
|
2910
2519
|
const region = this.effectRegion(layer);
|
|
2911
2520
|
const m = effectsMargin(layer.effects);
|
|
2912
2521
|
if (effectsAreLocal(activeEffectItems(layer.effects))) {
|
|
@@ -2982,7 +2591,7 @@ var RasterCompositor = (_class = class {
|
|
|
2982
2591
|
* without filters or a feathered or parametric mask (those spread a change beyond it).
|
|
2983
2592
|
*/
|
|
2984
2593
|
dirtyCoversShape(layer) {
|
|
2985
|
-
if (!this.isPixel(layer) || _optionalChain([this, 'access',
|
|
2594
|
+
if (!this.isPixel(layer) || _optionalChain([this, 'access', _25 => _25.profile, 'access', _26 => _26.pixelFilters, 'optionalCall', _27 => _27(layer)])) return false;
|
|
2986
2595
|
const mask = layer.mask;
|
|
2987
2596
|
return !mask || mask.enabled === false || !mask.source && !((_nullishCoalesce(mask.feather, () => ( 0))) > 0);
|
|
2988
2597
|
}
|
|
@@ -2999,7 +2608,7 @@ var RasterCompositor = (_class = class {
|
|
|
2999
2608
|
/** A content or group layer's own pixels over `r` with its mask applied to alpha, or `null` when empty. */
|
|
3000
2609
|
ownPixels(layer, r) {
|
|
3001
2610
|
let rgba;
|
|
3002
|
-
if (
|
|
2611
|
+
if (isGroup(layer)) {
|
|
3003
2612
|
const buf = new Uint8ClampedArray(r.width * r.height * 4);
|
|
3004
2613
|
rgba = this.runSteps(this.buildSteps(_nullishCoalesce(layer.children, () => ( []))), buf, true, r) ? null : buf;
|
|
3005
2614
|
} else {
|
|
@@ -3033,7 +2642,7 @@ var RasterCompositor = (_class = class {
|
|
|
3033
2642
|
const content = _nullishCoalesce(this.ownPixels(layer, a), () => ( new Uint8ClampedArray(a.width * a.height * 4)));
|
|
3034
2643
|
if (clipped.length) this.applyClipped(clipped, content, a);
|
|
3035
2644
|
const keep = keepAlpha ? sub.filter((_, i) => (i & 3) === 3) : null;
|
|
3036
|
-
const blend2 =
|
|
2645
|
+
const blend2 = isGroup(layer) ? layer.blend === "pass-through" ? "normal" : layer.blend : this.contentBlend(layer);
|
|
3037
2646
|
compositeLayerEffects({
|
|
3038
2647
|
backdrop: sub,
|
|
3039
2648
|
content,
|
|
@@ -3070,10 +2679,10 @@ var RasterCompositor = (_class = class {
|
|
|
3070
2679
|
*/
|
|
3071
2680
|
layerPixels(layer) {
|
|
3072
2681
|
const raw = this.sources.surfaceOf ? this.sources.surfaceOf(layer) : layer.surface;
|
|
3073
|
-
const ox = _nullishCoalesce(_optionalChain([layer, 'access',
|
|
3074
|
-
const oy = _nullishCoalesce(_optionalChain([layer, 'access',
|
|
3075
|
-
const filters = _nullishCoalesce(_optionalChain([this, 'access',
|
|
3076
|
-
if (!_optionalChain([filters, 'optionalAccess',
|
|
2682
|
+
const ox = _nullishCoalesce(_optionalChain([layer, 'access', _28 => _28.offset, 'optionalAccess', _29 => _29.x]), () => ( 0));
|
|
2683
|
+
const oy = _nullishCoalesce(_optionalChain([layer, 'access', _30 => _30.offset, 'optionalAccess', _31 => _31.y]), () => ( 0));
|
|
2684
|
+
const filters = _nullishCoalesce(_optionalChain([this, 'access', _32 => _32.profile, 'access', _33 => _33.pixelFilters, 'optionalCall', _34 => _34(layer)]), () => ( null));
|
|
2685
|
+
if (!_optionalChain([filters, 'optionalAccess', _35 => _35.spatial])) return { surface: raw, dx: ox, dy: oy, perPixel: filters };
|
|
3077
2686
|
const fkey = `${ox},${oy}:${filters.key}`;
|
|
3078
2687
|
let byKey = this.filteredCache.get(raw);
|
|
3079
2688
|
if (!byKey) {
|
|
@@ -3090,7 +2699,7 @@ var RasterCompositor = (_class = class {
|
|
|
3090
2699
|
}
|
|
3091
2700
|
/** RGBA of a content layer over `r` (document space, inside one tile), or `null` when it has nothing there. */
|
|
3092
2701
|
contentTile(layer, r) {
|
|
3093
|
-
if (!this.isPixel(layer)) return _nullishCoalesce(_optionalChain([this, 'access',
|
|
2702
|
+
if (!this.isPixel(layer)) return _nullishCoalesce(_optionalChain([this, 'access', _36 => _36.profile, 'access', _37 => _37.contentTile, 'optionalCall', _38 => _38(layer, r, this.sources)]), () => ( null));
|
|
3094
2703
|
const { surface, dx, dy, perPixel } = this.layerPixels(layer);
|
|
3095
2704
|
const src = { x: r.x - dx, y: r.y - dy, width: r.width, height: r.height };
|
|
3096
2705
|
const covered = _chunk474IQG74cjs.tilesInRect.call(void 0, src).map((t) => surface.getTile(t.tx, t.ty));
|
|
@@ -3105,7 +2714,7 @@ var RasterCompositor = (_class = class {
|
|
|
3105
2714
|
let byKey = this.contentCache.get(anchor);
|
|
3106
2715
|
const refsKey = `${r.x},${r.y}:${fkey}`;
|
|
3107
2716
|
if (aligned) {
|
|
3108
|
-
const hit = _optionalChain([byKey, 'optionalAccess',
|
|
2717
|
+
const hit = _optionalChain([byKey, 'optionalAccess', _39 => _39.get, 'call', _40 => _40(refsKey)]);
|
|
3109
2718
|
if (hit) return hit;
|
|
3110
2719
|
}
|
|
3111
2720
|
const data = _chunk474IQG74cjs.readRegion.call(void 0, surface, src);
|
|
@@ -3119,93 +2728,283 @@ var RasterCompositor = (_class = class {
|
|
|
3119
2728
|
}
|
|
3120
2729
|
return data;
|
|
3121
2730
|
}
|
|
3122
|
-
// --- Masks -------------------------------------------------------------------
|
|
3123
|
-
planeKey(mask, ox, oy) {
|
|
3124
|
-
const W = this.sources.width;
|
|
3125
|
-
const H = this.sources.height;
|
|
3126
|
-
let id = this.planeIds.get(mask.surface);
|
|
3127
|
-
if (id === void 0) {
|
|
3128
|
-
id = this.nextPlaneId++;
|
|
3129
|
-
this.planeIds.set(mask.surface, id);
|
|
3130
|
-
}
|
|
3131
|
-
return `${id}:${ox},${oy}:${W}x${H}:${_nullishCoalesce(mask.feather, () => ( 0))}:${_nullishCoalesce(mask.density, () => ( 1))}:${mask.source ? JSON.stringify(mask.source) : ""}`;
|
|
2731
|
+
// --- Masks -------------------------------------------------------------------
|
|
2732
|
+
planeKey(mask, ox, oy) {
|
|
2733
|
+
const W = this.sources.width;
|
|
2734
|
+
const H = this.sources.height;
|
|
2735
|
+
let id = this.planeIds.get(mask.surface);
|
|
2736
|
+
if (id === void 0) {
|
|
2737
|
+
id = this.nextPlaneId++;
|
|
2738
|
+
this.planeIds.set(mask.surface, id);
|
|
2739
|
+
}
|
|
2740
|
+
return `${id}:${ox},${oy}:${W}x${H}:${_nullishCoalesce(mask.feather, () => ( 0))}:${_nullishCoalesce(mask.density, () => ( 1))}:${mask.source ? JSON.stringify(mask.source) : ""}`;
|
|
2741
|
+
}
|
|
2742
|
+
/** Canvas-sized coverage of a feathered or parametric mask (cached). */
|
|
2743
|
+
planeFor(mask, ox, oy) {
|
|
2744
|
+
const key = this.planeKey(mask, ox, oy);
|
|
2745
|
+
let plane = this.planeCache.get(key);
|
|
2746
|
+
if (plane) {
|
|
2747
|
+
this.planeCache.delete(key);
|
|
2748
|
+
this.planeCache.set(key, plane);
|
|
2749
|
+
return plane;
|
|
2750
|
+
}
|
|
2751
|
+
const W = this.sources.width;
|
|
2752
|
+
const H = this.sources.height;
|
|
2753
|
+
let v = new Float32Array(W * H);
|
|
2754
|
+
if (mask.source) {
|
|
2755
|
+
const generated = _nullishCoalesce(_optionalChain([this, 'access', _41 => _41.profile, 'access', _42 => _42.maskSourcePlane, 'optionalCall', _43 => _43(mask.source, W, H, this.sources)]), () => ( null));
|
|
2756
|
+
if (!generated || generated.length !== W * H) v.fill(1);
|
|
2757
|
+
else v.set(generated);
|
|
2758
|
+
} else {
|
|
2759
|
+
const bytes = _chunk474IQG74cjs.readRegion.call(void 0, mask.surface, { x: -ox, y: -oy, width: W, height: H });
|
|
2760
|
+
for (let i = 0; i < v.length; i++) v[i] = bytes[i] / 255;
|
|
2761
|
+
}
|
|
2762
|
+
const feather = _nullishCoalesce(mask.feather, () => ( 0));
|
|
2763
|
+
if (feather > 0) v = _chunkK6PXS6DOcjs.gaussianBlur.call(void 0, v, W, H, feather, "clamp");
|
|
2764
|
+
const density = _nullishCoalesce(mask.density, () => ( 1));
|
|
2765
|
+
if (density !== 1) for (let i = 0; i < v.length; i++) v[i] = 1 - density * (1 - v[i]);
|
|
2766
|
+
plane = { data: v, width: W, height: H };
|
|
2767
|
+
this.planeCache.set(key, plane);
|
|
2768
|
+
while (this.planeCache.size > 8) this.planeCache.delete(this.planeCache.keys().next().value);
|
|
2769
|
+
return plane;
|
|
2770
|
+
}
|
|
2771
|
+
maskTile(layer, r) {
|
|
2772
|
+
const mask = layer.mask;
|
|
2773
|
+
if (!mask || mask.enabled === false) return null;
|
|
2774
|
+
const ox = this.isPixel(layer) ? _nullishCoalesce(_optionalChain([layer, 'access', _44 => _44.offset, 'optionalAccess', _45 => _45.x]), () => ( 0)) : 0;
|
|
2775
|
+
const oy = this.isPixel(layer) ? _nullishCoalesce(_optionalChain([layer, 'access', _46 => _46.offset, 'optionalAccess', _47 => _47.y]), () => ( 0)) : 0;
|
|
2776
|
+
const n = r.width * r.height;
|
|
2777
|
+
const out = new Float32Array(n);
|
|
2778
|
+
const density = _nullishCoalesce(mask.density, () => ( 1));
|
|
2779
|
+
if (mask.source || (_nullishCoalesce(mask.feather, () => ( 0))) > 0) {
|
|
2780
|
+
const plane = this.planeFor(mask, ox, oy);
|
|
2781
|
+
const W = plane.width;
|
|
2782
|
+
const H = plane.height;
|
|
2783
|
+
const outside = mask.source ? 1 : 1 - density * (1 - mask.defaultValue / 255);
|
|
2784
|
+
out.fill(outside);
|
|
2785
|
+
const x0 = Math.max(0, r.x);
|
|
2786
|
+
const y0 = Math.max(0, r.y);
|
|
2787
|
+
const x1 = Math.min(W, r.x + r.width);
|
|
2788
|
+
const y1 = Math.min(H, r.y + r.height);
|
|
2789
|
+
for (let y = y0; y < y1; y++) {
|
|
2790
|
+
const s = y * W;
|
|
2791
|
+
const d = (y - r.y) * r.width - r.x;
|
|
2792
|
+
for (let x = x0; x < x1; x++) out[d + x] = plane.data[s + x];
|
|
2793
|
+
}
|
|
2794
|
+
} else {
|
|
2795
|
+
const rect = { x: r.x - ox, y: r.y - oy, width: r.width, height: r.height };
|
|
2796
|
+
let all = true;
|
|
2797
|
+
if (maskDepth(mask.surface) !== 8) {
|
|
2798
|
+
const d = _chunkOLNIPTB3cjs.readDeepRegion.call(void 0, mask.surface, rect, 32);
|
|
2799
|
+
for (let i = 0; i < n; i++) {
|
|
2800
|
+
const v = d[i] <= 0 ? 0 : d[i] >= 1 ? 1 : d[i];
|
|
2801
|
+
out[i] = v;
|
|
2802
|
+
if (v !== 1) all = false;
|
|
2803
|
+
}
|
|
2804
|
+
} else {
|
|
2805
|
+
const bytes = _chunk474IQG74cjs.readRegion.call(void 0, mask.surface, rect);
|
|
2806
|
+
for (let i = 0; i < n; i++) {
|
|
2807
|
+
out[i] = bytes[i] / 255;
|
|
2808
|
+
if (bytes[i] !== 255) all = false;
|
|
2809
|
+
}
|
|
2810
|
+
}
|
|
2811
|
+
if (all) return null;
|
|
2812
|
+
if (density !== 1) for (let i = 0; i < n; i++) out[i] = 1 - density * (1 - out[i]);
|
|
2813
|
+
}
|
|
2814
|
+
return out;
|
|
2815
|
+
}
|
|
2816
|
+
// --- Running steps ---------------------------------------------------------
|
|
2817
|
+
/** Runs one step onto `acc`; returns whether `acc` is still empty. */
|
|
2818
|
+
runStep(step, acc, empty, r) {
|
|
2819
|
+
if (step.kind === "adjust") {
|
|
2820
|
+
if (empty) return true;
|
|
2821
|
+
this.applyFilterRun(step.layers, acc, r);
|
|
2822
|
+
return false;
|
|
2823
|
+
}
|
|
2824
|
+
const layer = step.layer;
|
|
2825
|
+
if (!layer.visible) return empty;
|
|
2826
|
+
const clipped = step.clipped.filter((l) => l.visible);
|
|
2827
|
+
if (this.hasEffects(layer)) return this.runEffectStep(layer, clipped, acc, empty, r);
|
|
2828
|
+
const coverage = this.maskTile(layer, r);
|
|
2829
|
+
if (coverage && coverage.every((v) => v <= 0)) return empty;
|
|
2830
|
+
if (step.kind === "group") {
|
|
2831
|
+
if (layer.blend === "pass-through" && !clipped.length) {
|
|
2832
|
+
if (layer.opacity >= 1 && !coverage) return this.runSteps(step.steps, acc, empty, r);
|
|
2833
|
+
const before = new Uint8ClampedArray(acc);
|
|
2834
|
+
const stillEmpty = this.runSteps(step.steps, acc, empty, r);
|
|
2835
|
+
lerpTile(acc, before, layer.opacity, coverage);
|
|
2836
|
+
return empty && stillEmpty;
|
|
2837
|
+
}
|
|
2838
|
+
const buf2 = new Uint8ClampedArray(acc.length);
|
|
2839
|
+
if (this.runSteps(step.steps, buf2, true, r)) return empty;
|
|
2840
|
+
this.applyClipped(clipped, buf2, r);
|
|
2841
|
+
const mode = layer.blend === "pass-through" ? "normal" : layer.blend;
|
|
2842
|
+
return this.blendOnto(acc, buf2, empty, mode, layer.opacity, coverage);
|
|
2843
|
+
}
|
|
2844
|
+
let content = this.contentTile(step.layer, r);
|
|
2845
|
+
if (!content) return empty;
|
|
2846
|
+
const ambient = _nullishCoalesce(_optionalChain([layer, 'access', _48 => _48.edge, 'optionalAccess', _49 => _49.ambient]), () => ( 0));
|
|
2847
|
+
if (ambient > 0 && (!empty || _optionalChain([layer, 'access', _50 => _50.edge, 'optionalAccess', _51 => _51.ambientColor]))) {
|
|
2848
|
+
content = new Uint8ClampedArray(content);
|
|
2849
|
+
applyEdgeAmbient(content, acc, coverage, ambient, _nullishCoalesce(_optionalChain([layer, 'access', _52 => _52.edge, 'optionalAccess', _53 => _53.ambientColor]), () => ( null)), 255);
|
|
2850
|
+
}
|
|
2851
|
+
const fill2 = this.isPixel(step.layer) ? _nullishCoalesce(step.layer.fillOpacity, () => ( 1)) : 1;
|
|
2852
|
+
const blend2 = this.contentBlend(step.layer);
|
|
2853
|
+
if (!clipped.length) return this.blendOnto(acc, content, empty, blend2, layer.opacity * fill2, coverage);
|
|
2854
|
+
const buf = new Uint8ClampedArray(acc.length);
|
|
2855
|
+
blendTile(buf, content, "normal", fill2, coverage);
|
|
2856
|
+
this.applyClipped(clipped, buf, r);
|
|
2857
|
+
return this.blendOnto(acc, buf, empty, blend2, layer.opacity, null);
|
|
2858
|
+
}
|
|
2859
|
+
runSteps(steps, acc, empty, r) {
|
|
2860
|
+
for (const s of steps) empty = this.runStep(s, acc, empty, r);
|
|
2861
|
+
return empty;
|
|
2862
|
+
}
|
|
2863
|
+
contentBlend(layer) {
|
|
2864
|
+
return _nullishCoalesce(_optionalChain([this, 'access', _54 => _54.profile, 'access', _55 => _55.contentBlend, 'optionalCall', _56 => _56(layer)]), () => ( layer.blend));
|
|
2865
|
+
}
|
|
2866
|
+
blendOnto(acc, src, empty, mode, alpha, coverage) {
|
|
2867
|
+
if (!(alpha > 0)) return empty;
|
|
2868
|
+
if (empty && mode === "normal" && alpha >= 1 && !coverage) {
|
|
2869
|
+
acc.set(src);
|
|
2870
|
+
return false;
|
|
2871
|
+
}
|
|
2872
|
+
blendTile(acc, src, mode, alpha, coverage);
|
|
2873
|
+
return false;
|
|
2874
|
+
}
|
|
2875
|
+
applyClipped(clipped, buf, r) {
|
|
2876
|
+
let run = [];
|
|
2877
|
+
const flush = () => {
|
|
2878
|
+
if (run.length) this.applyFilterRun(run, buf, r);
|
|
2879
|
+
run = [];
|
|
2880
|
+
};
|
|
2881
|
+
for (const c of clipped) {
|
|
2882
|
+
if (this.isFilter(c)) {
|
|
2883
|
+
run.push(c);
|
|
2884
|
+
continue;
|
|
2885
|
+
}
|
|
2886
|
+
flush();
|
|
2887
|
+
if (this.hasEffects(c) && !isGroup(c)) {
|
|
2888
|
+
this.compositeEffects(c, [], buf, r, true);
|
|
2889
|
+
continue;
|
|
2890
|
+
}
|
|
2891
|
+
const coverage = this.maskTile(c, r);
|
|
2892
|
+
if (isGroup(c)) {
|
|
2893
|
+
const inner = new Uint8ClampedArray(buf.length);
|
|
2894
|
+
if (this.runSteps(this.buildSteps(_nullishCoalesce(c.children, () => ( []))), inner, true, r)) continue;
|
|
2895
|
+
const mode = c.blend === "pass-through" ? "normal" : c.blend;
|
|
2896
|
+
blendAtop(buf, inner, mode, c.opacity, coverage);
|
|
2897
|
+
continue;
|
|
2898
|
+
}
|
|
2899
|
+
const content = this.contentTile(c, r);
|
|
2900
|
+
if (!content) continue;
|
|
2901
|
+
const fill2 = this.isPixel(c) ? _nullishCoalesce(c.fillOpacity, () => ( 1)) : 1;
|
|
2902
|
+
blendAtop(buf, content, this.contentBlend(c), c.opacity * fill2, coverage);
|
|
2903
|
+
}
|
|
2904
|
+
flush();
|
|
2905
|
+
}
|
|
2906
|
+
applyFilterRun(layers, acc, r) {
|
|
2907
|
+
const visible = [];
|
|
2908
|
+
let masks;
|
|
2909
|
+
for (const node of layers) {
|
|
2910
|
+
if (!node.visible) continue;
|
|
2911
|
+
const cov = this.maskTile(node, r);
|
|
2912
|
+
if (cov) {
|
|
2913
|
+
if (cov.every((v) => v <= 0)) continue;
|
|
2914
|
+
(masks ??= /* @__PURE__ */ new Map()).set(node.id, cov);
|
|
2915
|
+
}
|
|
2916
|
+
visible.push(node);
|
|
2917
|
+
}
|
|
2918
|
+
if (visible.length) _optionalChain([this, 'access', _57 => _57.profile, 'access', _58 => _58.applyFilterRun, 'optionalCall', _59 => _59(visible, acc, r, masks, this.sources)]);
|
|
2919
|
+
}
|
|
2920
|
+
}, _class);
|
|
2921
|
+
function filterOverCanvas(surface, ox, oy, filters, width, height) {
|
|
2922
|
+
if (width <= 0 || height <= 0) return _chunk474IQG74cjs.emptySurface.call(void 0, 4);
|
|
2923
|
+
const data = _chunk474IQG74cjs.readRegion.call(void 0, surface, { x: -ox, y: -oy, width, height });
|
|
2924
|
+
filters.apply(data, width, height);
|
|
2925
|
+
return _chunk474IQG74cjs.surfaceFromPixels.call(void 0, { width, height, data }, 4, 0, 0);
|
|
2926
|
+
}
|
|
2927
|
+
function copyRect(data, r, a) {
|
|
2928
|
+
const out = new Uint8ClampedArray(a.width * a.height * 4);
|
|
2929
|
+
for (let y = 0; y < a.height; y++) {
|
|
2930
|
+
const s = ((a.y - r.y + y) * r.width + (a.x - r.x)) * 4;
|
|
2931
|
+
out.set(data.subarray(s, s + a.width * 4), y * a.width * 4);
|
|
2932
|
+
}
|
|
2933
|
+
return out;
|
|
2934
|
+
}
|
|
2935
|
+
function pasteRect(data, r, part, a) {
|
|
2936
|
+
for (let y = 0; y < a.height; y++) data.set(part.subarray(y * a.width * 4, (y + 1) * a.width * 4), ((a.y - r.y + y) * r.width + (a.x - r.x)) * 4);
|
|
2937
|
+
}
|
|
2938
|
+
function sameRect(a, b) {
|
|
2939
|
+
return a.x === b.x && a.y === b.y && a.width === b.width && a.height === b.height;
|
|
2940
|
+
}
|
|
2941
|
+
function inflateRect(r, m) {
|
|
2942
|
+
return { x: r.x - m, y: r.y - m, width: r.width + 2 * m, height: r.height + 2 * m };
|
|
2943
|
+
}
|
|
2944
|
+
function intersectRect(a, b) {
|
|
2945
|
+
const x0 = Math.max(a.x, b.x);
|
|
2946
|
+
const y0 = Math.max(a.y, b.y);
|
|
2947
|
+
const x1 = Math.min(a.x + a.width, b.x + b.width);
|
|
2948
|
+
const y1 = Math.min(a.y + a.height, b.y + b.height);
|
|
2949
|
+
return x1 <= x0 || y1 <= y0 ? { x: x0, y: y0, width: 0, height: 0 } : { x: x0, y: y0, width: x1 - x0, height: y1 - y0 };
|
|
2950
|
+
}
|
|
2951
|
+
function changedTiles(a, b) {
|
|
2952
|
+
const out = [];
|
|
2953
|
+
for (const [k, t] of b.tiles) if (a.tiles.get(k) !== t) out.push(k);
|
|
2954
|
+
for (const k of a.tiles.keys()) if (!b.tiles.has(k)) out.push(k);
|
|
2955
|
+
return out;
|
|
2956
|
+
}
|
|
2957
|
+
|
|
2958
|
+
// src/raster/deep-compositor.ts
|
|
2959
|
+
var isGroup2 = (l) => l.type === "group";
|
|
2960
|
+
var DeepCompositor = class {
|
|
2961
|
+
constructor(base, profile, deep, depth) {
|
|
2962
|
+
this.base = base;
|
|
2963
|
+
this.profile = profile;
|
|
2964
|
+
this.deep = deep;
|
|
2965
|
+
this.depth = depth;
|
|
2966
|
+
this.linear = depth === 32;
|
|
2967
|
+
}
|
|
2968
|
+
|
|
2969
|
+
|
|
2970
|
+
|
|
2971
|
+
|
|
2972
|
+
|
|
2973
|
+
|
|
2974
|
+
/** The composite of `layers` over `rect` as float RGBA in the working space (`rect.width × rect.height × 4`). */
|
|
2975
|
+
composite(layers, rect, sources) {
|
|
2976
|
+
this.sources = sources;
|
|
2977
|
+
const acc = new Float32Array(Math.max(0, rect.width * rect.height * 4));
|
|
2978
|
+
if (rect.width > 0 && rect.height > 0) this.runSteps(this.buildSteps(layers), acc, true, rect);
|
|
2979
|
+
return acc;
|
|
2980
|
+
}
|
|
2981
|
+
// --- Steps (as RasterCompositor.buildSteps) ------------------------------------
|
|
2982
|
+
isPixel(l) {
|
|
2983
|
+
return l.type === "pixel" || (_nullishCoalesce(_optionalChain([this, 'access', _60 => _60.profile, 'access', _61 => _61.isPixelLike, 'optionalCall', _62 => _62(l)]), () => ( false)));
|
|
3132
2984
|
}
|
|
3133
|
-
|
|
3134
|
-
|
|
3135
|
-
const key = this.planeKey(mask, ox, oy);
|
|
3136
|
-
let plane = this.planeCache.get(key);
|
|
3137
|
-
if (plane) {
|
|
3138
|
-
this.planeCache.delete(key);
|
|
3139
|
-
this.planeCache.set(key, plane);
|
|
3140
|
-
return plane;
|
|
3141
|
-
}
|
|
3142
|
-
const W = this.sources.width;
|
|
3143
|
-
const H = this.sources.height;
|
|
3144
|
-
let v = new Float32Array(W * H);
|
|
3145
|
-
if (mask.source) {
|
|
3146
|
-
const generated = _nullishCoalesce(_optionalChain([this, 'access', _70 => _70.profile, 'access', _71 => _71.maskSourcePlane, 'optionalCall', _72 => _72(mask.source, W, H, this.sources)]), () => ( null));
|
|
3147
|
-
if (!generated || generated.length !== W * H) v.fill(1);
|
|
3148
|
-
else v.set(generated);
|
|
3149
|
-
} else {
|
|
3150
|
-
const bytes = _chunk474IQG74cjs.readRegion.call(void 0, mask.surface, { x: -ox, y: -oy, width: W, height: H });
|
|
3151
|
-
for (let i = 0; i < v.length; i++) v[i] = bytes[i] / 255;
|
|
3152
|
-
}
|
|
3153
|
-
const feather = _nullishCoalesce(mask.feather, () => ( 0));
|
|
3154
|
-
if (feather > 0) v = _chunkK6PXS6DOcjs.gaussianBlur.call(void 0, v, W, H, feather, "clamp");
|
|
3155
|
-
const density = _nullishCoalesce(mask.density, () => ( 1));
|
|
3156
|
-
if (density !== 1) for (let i = 0; i < v.length; i++) v[i] = 1 - density * (1 - v[i]);
|
|
3157
|
-
plane = { data: v, width: W, height: H };
|
|
3158
|
-
this.planeCache.set(key, plane);
|
|
3159
|
-
while (this.planeCache.size > 8) this.planeCache.delete(this.planeCache.keys().next().value);
|
|
3160
|
-
return plane;
|
|
2985
|
+
isFilter(l) {
|
|
2986
|
+
return _nullishCoalesce(_optionalChain([this, 'access', _63 => _63.profile, 'access', _64 => _64.isFilterLayer, 'optionalCall', _65 => _65(l)]), () => ( false));
|
|
3161
2987
|
}
|
|
3162
|
-
|
|
3163
|
-
const
|
|
3164
|
-
|
|
3165
|
-
|
|
3166
|
-
|
|
3167
|
-
|
|
3168
|
-
|
|
3169
|
-
const density = _nullishCoalesce(mask.density, () => ( 1));
|
|
3170
|
-
if (mask.source || (_nullishCoalesce(mask.feather, () => ( 0))) > 0) {
|
|
3171
|
-
const plane = this.planeFor(mask, ox, oy);
|
|
3172
|
-
const W = plane.width;
|
|
3173
|
-
const H = plane.height;
|
|
3174
|
-
const outside = mask.source ? 1 : 1 - density * (1 - mask.defaultValue / 255);
|
|
3175
|
-
out.fill(outside);
|
|
3176
|
-
const x0 = Math.max(0, r.x);
|
|
3177
|
-
const y0 = Math.max(0, r.y);
|
|
3178
|
-
const x1 = Math.min(W, r.x + r.width);
|
|
3179
|
-
const y1 = Math.min(H, r.y + r.height);
|
|
3180
|
-
for (let y = y0; y < y1; y++) {
|
|
3181
|
-
const s = y * W;
|
|
3182
|
-
const d = (y - r.y) * r.width - r.x;
|
|
3183
|
-
for (let x = x0; x < x1; x++) out[d + x] = plane.data[s + x];
|
|
3184
|
-
}
|
|
3185
|
-
} else {
|
|
3186
|
-
const rect = { x: r.x - ox, y: r.y - oy, width: r.width, height: r.height };
|
|
3187
|
-
let all = true;
|
|
3188
|
-
if (maskDepth(mask.surface) !== 8) {
|
|
3189
|
-
const d = _chunkOLNIPTB3cjs.readDeepRegion.call(void 0, mask.surface, rect, 32);
|
|
3190
|
-
for (let i = 0; i < n; i++) {
|
|
3191
|
-
const v = d[i] <= 0 ? 0 : d[i] >= 1 ? 1 : d[i];
|
|
3192
|
-
out[i] = v;
|
|
3193
|
-
if (v !== 1) all = false;
|
|
3194
|
-
}
|
|
3195
|
-
} else {
|
|
3196
|
-
const bytes = _chunk474IQG74cjs.readRegion.call(void 0, mask.surface, rect);
|
|
3197
|
-
for (let i = 0; i < n; i++) {
|
|
3198
|
-
out[i] = bytes[i] / 255;
|
|
3199
|
-
if (bytes[i] !== 255) all = false;
|
|
3200
|
-
}
|
|
2988
|
+
buildSteps(layers) {
|
|
2989
|
+
const steps = [];
|
|
2990
|
+
for (const layer of layers) {
|
|
2991
|
+
const last = steps[steps.length - 1];
|
|
2992
|
+
if (layer.clipped && last && (last.kind === "content" || last.kind === "group")) {
|
|
2993
|
+
last.clipped.push(layer);
|
|
2994
|
+
continue;
|
|
3201
2995
|
}
|
|
3202
|
-
if (
|
|
3203
|
-
|
|
2996
|
+
if (this.isFilter(layer)) {
|
|
2997
|
+
if (last && last.kind === "adjust") last.layers.push(layer);
|
|
2998
|
+
else steps.push({ kind: "adjust", layers: [layer] });
|
|
2999
|
+
} else if (isGroup2(layer)) steps.push({ kind: "group", layer, clipped: [], steps: this.buildSteps(_nullishCoalesce(layer.children, () => ( []))) });
|
|
3000
|
+
else steps.push({ kind: "content", layer, clipped: [] });
|
|
3204
3001
|
}
|
|
3205
|
-
return
|
|
3002
|
+
return steps;
|
|
3003
|
+
}
|
|
3004
|
+
runSteps(steps, acc, empty, r) {
|
|
3005
|
+
for (const s of steps) empty = this.runStep(s, acc, empty, r);
|
|
3006
|
+
return empty;
|
|
3206
3007
|
}
|
|
3207
|
-
// --- Running steps ---------------------------------------------------------
|
|
3208
|
-
/** Runs one step onto `acc`; returns whether `acc` is still empty. */
|
|
3209
3008
|
runStep(step, acc, empty, r) {
|
|
3210
3009
|
if (step.kind === "adjust") {
|
|
3211
3010
|
if (empty) return true;
|
|
@@ -3215,131 +3014,368 @@ var RasterCompositor = (_class = class {
|
|
|
3215
3014
|
const layer = step.layer;
|
|
3216
3015
|
if (!layer.visible) return empty;
|
|
3217
3016
|
const clipped = step.clipped.filter((l) => l.visible);
|
|
3218
|
-
if (this.
|
|
3219
|
-
const coverage = this.
|
|
3017
|
+
if ((step.kind === "content" || step.kind === "group") && this.deepEffects(layer)) return this.runEffects(layer, clipped, acc, r, step.kind === "group" ? step.steps : null) ? false : empty;
|
|
3018
|
+
const coverage = this.renderedAlone(layer) ? null : this.base.maskCoverage(layer, r, this.sources);
|
|
3220
3019
|
if (coverage && coverage.every((v) => v <= 0)) return empty;
|
|
3221
|
-
if (step.kind === "group") {
|
|
3020
|
+
if (step.kind === "group" && !this.renderedAlone(layer)) {
|
|
3222
3021
|
if (layer.blend === "pass-through" && !clipped.length) {
|
|
3223
3022
|
if (layer.opacity >= 1 && !coverage) return this.runSteps(step.steps, acc, empty, r);
|
|
3224
|
-
const before =
|
|
3023
|
+
const before = acc.slice();
|
|
3225
3024
|
const stillEmpty = this.runSteps(step.steps, acc, empty, r);
|
|
3226
|
-
|
|
3025
|
+
lerp(acc, before, layer.opacity, coverage);
|
|
3227
3026
|
return empty && stillEmpty;
|
|
3228
3027
|
}
|
|
3229
|
-
const buf2 = new
|
|
3230
|
-
if (this.runSteps(step.steps, buf2, true, r)) return empty;
|
|
3231
|
-
this.applyClipped(clipped, buf2, r);
|
|
3232
|
-
const
|
|
3233
|
-
|
|
3028
|
+
const buf2 = new Float32Array(acc.length);
|
|
3029
|
+
if (this.runSteps(step.steps, buf2, true, r)) return empty;
|
|
3030
|
+
this.applyClipped(clipped, buf2, r);
|
|
3031
|
+
const mode2 = layer.blend === "pass-through" ? "normal" : layer.blend;
|
|
3032
|
+
this.blend(acc, buf2, mode2, layer.opacity, coverage);
|
|
3033
|
+
return false;
|
|
3034
|
+
}
|
|
3035
|
+
const content = this.content(layer, r);
|
|
3036
|
+
if (!content) return empty;
|
|
3037
|
+
const ambient = _nullishCoalesce(_optionalChain([layer, 'access', _66 => _66.edge, 'optionalAccess', _67 => _67.ambient]), () => ( 0));
|
|
3038
|
+
if (ambient > 0) {
|
|
3039
|
+
const c = _optionalChain([layer, 'access', _68 => _68.edge, 'optionalAccess', _69 => _69.ambientColor]);
|
|
3040
|
+
const color2 = c ? c.map((v) => this.linear ? _chunkOLNIPTB3cjs.srgbDecode.call(void 0, v / 255) : v / 255) : null;
|
|
3041
|
+
if (color2 || !empty) applyEdgeAmbient(content, acc, coverage, ambient, color2, 1);
|
|
3042
|
+
}
|
|
3043
|
+
const alone = this.renderedAlone(layer);
|
|
3044
|
+
const fill2 = !alone && this.isPixel(layer) ? _nullishCoalesce(layer.fillOpacity, () => ( 1)) : 1;
|
|
3045
|
+
const mode = this.blendOf(layer);
|
|
3046
|
+
if (!clipped.length) {
|
|
3047
|
+
this.blend(acc, content, mode, layer.opacity * fill2, coverage);
|
|
3048
|
+
return false;
|
|
3049
|
+
}
|
|
3050
|
+
const buf = new Float32Array(acc.length);
|
|
3051
|
+
this.blend(buf, content, "normal", fill2, coverage);
|
|
3052
|
+
this.applyClipped(clipped, buf, r);
|
|
3053
|
+
this.blend(acc, buf, mode, layer.opacity, null);
|
|
3054
|
+
return false;
|
|
3055
|
+
}
|
|
3056
|
+
/**
|
|
3057
|
+
* A pixel layer with effects onto `acc` over `r`: its deep content (filters, mask, clipped
|
|
3058
|
+
* layers) and the effects composited in float. Effect maps come from the 8-bit shape. At 32
|
|
3059
|
+
* bits the effects composite in sRGB-encoded values (their colours and blends are defined
|
|
3060
|
+
* there) and the result is decoded back. Returns whether anything was drawn.
|
|
3061
|
+
*/
|
|
3062
|
+
runEffects(layer, clipped, acc, r, groupSteps = null) {
|
|
3063
|
+
const fx = this.base.effectsInput(layer, r, this.sources);
|
|
3064
|
+
if (!fx) return false;
|
|
3065
|
+
const a = fx.rect;
|
|
3066
|
+
let content;
|
|
3067
|
+
if (groupSteps) {
|
|
3068
|
+
content = new Float32Array(a.width * a.height * 4);
|
|
3069
|
+
this.runSteps(groupSteps, content, true, a);
|
|
3070
|
+
} else content = _nullishCoalesce(this.content(layer, a), () => ( new Float32Array(a.width * a.height * 4)));
|
|
3071
|
+
const coverage = this.base.maskCoverage(layer, a, this.sources);
|
|
3072
|
+
if (coverage) for (let i = 0; i < coverage.length; i++) content[i * 4 + 3] *= coverage[i];
|
|
3073
|
+
if (clipped.length) this.applyClipped(clipped, content, a);
|
|
3074
|
+
const sub = new Float32Array(a.width * a.height * 4);
|
|
3075
|
+
for (let y = 0; y < a.height; y++) {
|
|
3076
|
+
const s = ((a.y - r.y + y) * r.width + (a.x - r.x)) * 4;
|
|
3077
|
+
sub.set(acc.subarray(s, s + a.width * 4), y * a.width * 4);
|
|
3078
|
+
}
|
|
3079
|
+
if (this.linear) {
|
|
3080
|
+
encodeInPlace(sub);
|
|
3081
|
+
encodeInPlace(content);
|
|
3082
|
+
}
|
|
3083
|
+
compositeLayerEffects({ ...fx, backdrop: sub, content });
|
|
3084
|
+
if (this.linear) decodeInPlace(sub);
|
|
3085
|
+
for (let y = 0; y < a.height; y++) acc.set(sub.subarray(y * a.width * 4, (y + 1) * a.width * 4), ((a.y - r.y + y) * r.width + (a.x - r.x)) * 4);
|
|
3086
|
+
return true;
|
|
3087
|
+
}
|
|
3088
|
+
applyClipped(clipped, buf, r) {
|
|
3089
|
+
let run = [];
|
|
3090
|
+
const flush = () => {
|
|
3091
|
+
if (run.length) this.applyFilterRun(run, buf, r);
|
|
3092
|
+
run = [];
|
|
3093
|
+
};
|
|
3094
|
+
for (const c of clipped) {
|
|
3095
|
+
if (this.isFilter(c)) {
|
|
3096
|
+
run.push(c);
|
|
3097
|
+
continue;
|
|
3098
|
+
}
|
|
3099
|
+
flush();
|
|
3100
|
+
const alone = this.renderedAlone(c);
|
|
3101
|
+
const coverage = alone ? null : this.base.maskCoverage(c, r, this.sources);
|
|
3102
|
+
let src;
|
|
3103
|
+
if (isGroup2(c) && !alone) {
|
|
3104
|
+
src = new Float32Array(buf.length);
|
|
3105
|
+
if (this.runSteps(this.buildSteps(_nullishCoalesce(c.children, () => ( []))), src, true, r)) continue;
|
|
3106
|
+
} else src = this.content(c, r);
|
|
3107
|
+
if (!src) continue;
|
|
3108
|
+
const fill2 = !alone && this.isPixel(c) ? _nullishCoalesce(c.fillOpacity, () => ( 1)) : 1;
|
|
3109
|
+
const keep = new Float32Array(buf.length >> 2);
|
|
3110
|
+
for (let i = 3, p = 0; i < buf.length; i += 4, p++) keep[p] = buf[i];
|
|
3111
|
+
this.blend(buf, src, c.blend === "pass-through" ? "normal" : this.blendOf(c), c.opacity * fill2, coverage);
|
|
3112
|
+
for (let i = 3, p = 0; i < buf.length; i += 4, p++) buf[i] = keep[p];
|
|
3113
|
+
}
|
|
3114
|
+
flush();
|
|
3115
|
+
}
|
|
3116
|
+
applyFilterRun(layers, acc, r) {
|
|
3117
|
+
const visible = [];
|
|
3118
|
+
let masks;
|
|
3119
|
+
for (const node of layers) {
|
|
3120
|
+
if (!node.visible) continue;
|
|
3121
|
+
const cov = this.base.maskCoverage(node, r, this.sources);
|
|
3122
|
+
if (cov) {
|
|
3123
|
+
if (cov.every((v) => v <= 0)) continue;
|
|
3124
|
+
(masks ??= /* @__PURE__ */ new Map()).set(node.id, cov);
|
|
3125
|
+
}
|
|
3126
|
+
visible.push(node);
|
|
3127
|
+
}
|
|
3128
|
+
if (!visible.length) return;
|
|
3129
|
+
if (this.deep.applyFilterRunDeep) {
|
|
3130
|
+
if (this.linear) mapColour(acc, _chunkOLNIPTB3cjs.srgbEncode);
|
|
3131
|
+
this.deep.applyFilterRunDeep(visible, acc, r, masks, this.sources);
|
|
3132
|
+
if (this.linear) mapColour(acc, _chunkOLNIPTB3cjs.srgbDecode);
|
|
3133
|
+
return;
|
|
3134
|
+
}
|
|
3135
|
+
const bytes = this.to8(acc);
|
|
3136
|
+
_optionalChain([this, 'access', _70 => _70.profile, 'access', _71 => _71.applyFilterRun, 'optionalCall', _72 => _72(visible, bytes, r, masks, this.sources)]);
|
|
3137
|
+
acc.set(this.from8(bytes));
|
|
3138
|
+
}
|
|
3139
|
+
// --- Layer content ---------------------------------------------------------------
|
|
3140
|
+
/** Layers drawn by the 8-bit compositor alone (effects, pixel filters, content the editor draws). */
|
|
3141
|
+
/** A pixel(-like) layer or a group with effects: composited in float through `compositeLayerEffects`. */
|
|
3142
|
+
deepEffects(layer) {
|
|
3143
|
+
return hasActiveEffects(layer.effects) && !this.isFilter(layer) && (isGroup2(layer) || this.isPixel(layer));
|
|
3144
|
+
}
|
|
3145
|
+
renderedAlone(layer) {
|
|
3146
|
+
if (hasActiveEffects(layer.effects) && !this.isFilter(layer) && !this.deepEffects(layer)) return true;
|
|
3147
|
+
if (this.isPixel(layer)) return Boolean(_optionalChain([this, 'access', _73 => _73.profile, 'access', _74 => _74.pixelFilters, 'optionalCall', _75 => _75(layer)])) && !_optionalChain([this, 'access', _76 => _76.deep, 'access', _77 => _77.pixelFiltersDeep, 'optionalCall', _78 => _78(layer)]);
|
|
3148
|
+
return !isGroup2(layer);
|
|
3149
|
+
}
|
|
3150
|
+
blendOf(layer) {
|
|
3151
|
+
return _nullishCoalesce(_optionalChain([this, 'access', _79 => _79.profile, 'access', _80 => _80.contentBlend, 'optionalCall', _81 => _81(layer)]), () => ( layer.blend));
|
|
3152
|
+
}
|
|
3153
|
+
/** A layer's float RGBA over `r` (straight alpha, working space), or `null` when it has none there. */
|
|
3154
|
+
content(layer, r) {
|
|
3155
|
+
if (this.renderedAlone(layer)) {
|
|
3156
|
+
const edge = _optionalChain([layer, 'access', _82 => _82.edge, 'optionalAccess', _83 => _83.ambient]) ? { ...layer.edge, ambient: 0 } : layer.edge;
|
|
3157
|
+
const solo = { ...layer, blend: isGroup2(layer) && layer.blend === "pass-through" ? "pass-through" : "normal", opacity: 1, clipped: false, edge };
|
|
3158
|
+
const bytes = this.base.composite([solo], r, this.sources);
|
|
3159
|
+
return this.from8(bytes);
|
|
3160
|
+
}
|
|
3161
|
+
const surface = this.sources.surfaceOf ? this.sources.surfaceOf(layer) : layer.surface;
|
|
3162
|
+
if (!surface) return null;
|
|
3163
|
+
const ox = _nullishCoalesce(_optionalChain([layer, 'access', _84 => _84.offset, 'optionalAccess', _85 => _85.x]), () => ( 0));
|
|
3164
|
+
const oy = _nullishCoalesce(_optionalChain([layer, 'access', _86 => _86.offset, 'optionalAccess', _87 => _87.y]), () => ( 0));
|
|
3165
|
+
const filters = this.isPixel(layer) ? _nullishCoalesce(_optionalChain([this, 'access', _88 => _88.deep, 'access', _89 => _89.pixelFiltersDeep, 'optionalCall', _90 => _90(layer)]), () => ( null)) : null;
|
|
3166
|
+
if (!filters) return this.samples(surface, { x: r.x - ox, y: r.y - oy, width: r.width, height: r.height });
|
|
3167
|
+
const m = filters.reach;
|
|
3168
|
+
const W = this.sources.width;
|
|
3169
|
+
const H = this.sources.height;
|
|
3170
|
+
const x0 = m ? Math.max(0, r.x - m) : r.x;
|
|
3171
|
+
const y0 = m ? Math.max(0, r.y - m) : r.y;
|
|
3172
|
+
const x1 = m ? Math.min(W, r.x + r.width + m) : r.x + r.width;
|
|
3173
|
+
const y1 = m ? Math.min(H, r.y + r.height + m) : r.y + r.height;
|
|
3174
|
+
if (x1 <= x0 || y1 <= y0) return new Float32Array(r.width * r.height * 4);
|
|
3175
|
+
const big = { x: x0, y: y0, width: x1 - x0, height: y1 - y0 };
|
|
3176
|
+
const data = this.samples(surface, { ...big, x: big.x - ox, y: big.y - oy });
|
|
3177
|
+
filters.apply(data, big.width, big.height, this.linear);
|
|
3178
|
+
if (big.x === r.x && big.y === r.y && big.width === r.width && big.height === r.height) return data;
|
|
3179
|
+
const out = new Float32Array(r.width * r.height * 4);
|
|
3180
|
+
for (let y = 0; y < r.height; y++) {
|
|
3181
|
+
const sy = r.y + y - big.y;
|
|
3182
|
+
if (sy < 0 || sy >= big.height) continue;
|
|
3183
|
+
for (let x = 0; x < r.width; x++) {
|
|
3184
|
+
const sx = r.x + x - big.x;
|
|
3185
|
+
if (sx < 0 || sx >= big.width) continue;
|
|
3186
|
+
const s = (sy * big.width + sx) * 4;
|
|
3187
|
+
const d = (y * r.width + x) * 4;
|
|
3188
|
+
out[d] = data[s];
|
|
3189
|
+
out[d + 1] = data[s + 1];
|
|
3190
|
+
out[d + 2] = data[s + 2];
|
|
3191
|
+
out[d + 3] = data[s + 3];
|
|
3192
|
+
}
|
|
3234
3193
|
}
|
|
3235
|
-
|
|
3236
|
-
if (!content) return empty;
|
|
3237
|
-
const fill2 = this.isPixel(step.layer) ? _nullishCoalesce(step.layer.fillOpacity, () => ( 1)) : 1;
|
|
3238
|
-
const blend2 = this.contentBlend(step.layer);
|
|
3239
|
-
if (!clipped.length) return this.blendOnto(acc, content, empty, blend2, layer.opacity * fill2, coverage);
|
|
3240
|
-
const buf = new Uint8ClampedArray(acc.length);
|
|
3241
|
-
blendTile(buf, content, "normal", fill2, coverage);
|
|
3242
|
-
this.applyClipped(clipped, buf, r);
|
|
3243
|
-
return this.blendOnto(acc, buf, empty, blend2, layer.opacity, null);
|
|
3194
|
+
return out;
|
|
3244
3195
|
}
|
|
3245
|
-
|
|
3246
|
-
|
|
3247
|
-
|
|
3196
|
+
/** A surface's samples over `rect` (layer space) in the working space. */
|
|
3197
|
+
samples(surface, rect) {
|
|
3198
|
+
const samples = _chunkOLNIPTB3cjs.readDeepRegion.call(void 0, surface, rect, this.depth);
|
|
3199
|
+
if (samples instanceof Float32Array) return samples;
|
|
3200
|
+
const out = new Float32Array(samples.length);
|
|
3201
|
+
for (let i = 0; i < samples.length; i++) out[i] = samples[i] / 65535;
|
|
3202
|
+
return out;
|
|
3248
3203
|
}
|
|
3249
|
-
|
|
3250
|
-
|
|
3204
|
+
/** 8-bit RGBA to the working space. */
|
|
3205
|
+
from8(bytes) {
|
|
3206
|
+
if (this.linear) return _chunkOLNIPTB3cjs.to32From8.call(void 0, bytes, 4);
|
|
3207
|
+
const out = new Float32Array(bytes.length);
|
|
3208
|
+
for (let i = 0; i < bytes.length; i++) out[i] = bytes[i] / 255;
|
|
3209
|
+
return out;
|
|
3251
3210
|
}
|
|
3252
|
-
|
|
3253
|
-
|
|
3254
|
-
|
|
3255
|
-
|
|
3256
|
-
|
|
3211
|
+
/** The working space to 8-bit RGBA. */
|
|
3212
|
+
to8(acc) {
|
|
3213
|
+
const out = new Uint8ClampedArray(acc.length);
|
|
3214
|
+
for (let i = 0; i < acc.length; i += 4) {
|
|
3215
|
+
for (let c = 0; c < 3; c++) out[i + c] = Math.round((this.linear ? _chunkOLNIPTB3cjs.srgbEncode.call(void 0, acc[i + c]) : acc[i + c]) * 255);
|
|
3216
|
+
out[i + 3] = Math.round(acc[i + 3] * 255);
|
|
3257
3217
|
}
|
|
3258
|
-
|
|
3259
|
-
return false;
|
|
3218
|
+
return out;
|
|
3260
3219
|
}
|
|
3261
|
-
|
|
3262
|
-
|
|
3263
|
-
|
|
3264
|
-
|
|
3265
|
-
|
|
3266
|
-
|
|
3267
|
-
|
|
3268
|
-
|
|
3269
|
-
|
|
3220
|
+
// --- Blending --------------------------------------------------------------------
|
|
3221
|
+
/** `src` over `dst` with `mode` at `alpha` × coverage (straight alpha, float), as `blendTile`. */
|
|
3222
|
+
blend(dst, src, mode, alpha, coverage) {
|
|
3223
|
+
if (!(alpha > 0)) return;
|
|
3224
|
+
const normal = mode === "normal";
|
|
3225
|
+
const pigment = mode === "pigment";
|
|
3226
|
+
const cb = [0, 0, 0];
|
|
3227
|
+
const cs = [0, 0, 0];
|
|
3228
|
+
const mix = [0, 0, 0];
|
|
3229
|
+
for (let i = 0, p = 0; i < dst.length; i += 4, p++) {
|
|
3230
|
+
const sa = src[i + 3];
|
|
3231
|
+
if (!(sa > 0)) continue;
|
|
3232
|
+
const k = coverage ? alpha * coverage[p] : alpha;
|
|
3233
|
+
if (!(k > 0)) continue;
|
|
3234
|
+
const as = Math.min(1, sa * k);
|
|
3235
|
+
const ab = dst[i + 3];
|
|
3236
|
+
const ao = as + ab * (1 - as);
|
|
3237
|
+
if (ao <= 0) {
|
|
3238
|
+
dst[i] = dst[i + 1] = dst[i + 2] = dst[i + 3] = 0;
|
|
3270
3239
|
continue;
|
|
3271
3240
|
}
|
|
3272
|
-
|
|
3273
|
-
|
|
3274
|
-
|
|
3241
|
+
if (normal && as >= 1) {
|
|
3242
|
+
dst[i] = src[i];
|
|
3243
|
+
dst[i + 1] = src[i + 1];
|
|
3244
|
+
dst[i + 2] = src[i + 2];
|
|
3245
|
+
dst[i + 3] = 1;
|
|
3275
3246
|
continue;
|
|
3276
3247
|
}
|
|
3277
|
-
|
|
3278
|
-
|
|
3279
|
-
|
|
3280
|
-
|
|
3281
|
-
|
|
3282
|
-
|
|
3248
|
+
for (let c = 0; c < 3; c++) {
|
|
3249
|
+
cb[c] = dst[i + c];
|
|
3250
|
+
cs[c] = src[i + c];
|
|
3251
|
+
}
|
|
3252
|
+
if (pigment) {
|
|
3253
|
+
if (this.linear) for (let c = 0; c < 3; c++) cb[c] = _chunkOLNIPTB3cjs.srgbEncode.call(void 0, cb[c]), cs[c] = _chunkOLNIPTB3cjs.srgbEncode.call(void 0, cs[c]);
|
|
3254
|
+
_chunkOLNIPTB3cjs.mixPigmentRgb.call(void 0, cb, cs, as / ao, mix);
|
|
3255
|
+
for (let c = 0; c < 3; c++) dst[i + c] = this.linear ? _chunkOLNIPTB3cjs.srgbDecode.call(void 0, mix[c]) : mix[c];
|
|
3256
|
+
dst[i + 3] = ao;
|
|
3283
3257
|
continue;
|
|
3284
3258
|
}
|
|
3285
|
-
const
|
|
3286
|
-
|
|
3287
|
-
const
|
|
3288
|
-
|
|
3259
|
+
const m = normal ? cs : _chunkOLNIPTB3cjs.blendRgb.call(void 0, mode, cb, cs);
|
|
3260
|
+
const wb = (1 - as) * ab;
|
|
3261
|
+
const ws = (1 - ab) * as;
|
|
3262
|
+
const wm = as * ab;
|
|
3263
|
+
for (let c = 0; c < 3; c++) dst[i + c] = (wb * cb[c] + ws * cs[c] + wm * m[c]) / ao;
|
|
3264
|
+
dst[i + 3] = ao;
|
|
3289
3265
|
}
|
|
3290
|
-
flush();
|
|
3291
3266
|
}
|
|
3292
|
-
|
|
3293
|
-
|
|
3294
|
-
|
|
3295
|
-
|
|
3296
|
-
|
|
3297
|
-
|
|
3298
|
-
if (cov) {
|
|
3299
|
-
if (cov.every((v) => v <= 0)) continue;
|
|
3300
|
-
(masks ??= /* @__PURE__ */ new Map()).set(node.id, cov);
|
|
3301
|
-
}
|
|
3302
|
-
visible.push(node);
|
|
3303
|
-
}
|
|
3304
|
-
if (visible.length) _optionalChain([this, 'access', _80 => _80.profile, 'access', _81 => _81.applyFilterRun, 'optionalCall', _82 => _82(visible, acc, r, masks, this.sources)]);
|
|
3267
|
+
};
|
|
3268
|
+
function lerp(dst, before, alpha, coverage) {
|
|
3269
|
+
for (let i = 0, p = 0; i < dst.length; i += 4, p++) {
|
|
3270
|
+
const k = coverage ? alpha * coverage[p] : alpha;
|
|
3271
|
+
if (k >= 1) continue;
|
|
3272
|
+
for (let c = 0; c < 4; c++) dst[i + c] = before[i + c] + (dst[i + c] - before[i + c]) * k;
|
|
3305
3273
|
}
|
|
3306
|
-
}, _class);
|
|
3307
|
-
function filterOverCanvas(surface, ox, oy, filters, width, height) {
|
|
3308
|
-
if (width <= 0 || height <= 0) return _chunk474IQG74cjs.emptySurface.call(void 0, 4);
|
|
3309
|
-
const data = _chunk474IQG74cjs.readRegion.call(void 0, surface, { x: -ox, y: -oy, width, height });
|
|
3310
|
-
filters.apply(data, width, height);
|
|
3311
|
-
return _chunk474IQG74cjs.surfaceFromPixels.call(void 0, { width, height, data }, 4, 0, 0);
|
|
3312
3274
|
}
|
|
3313
|
-
function
|
|
3314
|
-
|
|
3315
|
-
|
|
3316
|
-
|
|
3317
|
-
|
|
3275
|
+
function mapColour(data, f) {
|
|
3276
|
+
for (let i = 0; i < data.length; i += 4) {
|
|
3277
|
+
data[i] = f(data[i]);
|
|
3278
|
+
data[i + 1] = f(data[i + 1]);
|
|
3279
|
+
data[i + 2] = f(data[i + 2]);
|
|
3318
3280
|
}
|
|
3319
|
-
return out;
|
|
3320
|
-
}
|
|
3321
|
-
function pasteRect(data, r, part, a) {
|
|
3322
|
-
for (let y = 0; y < a.height; y++) data.set(part.subarray(y * a.width * 4, (y + 1) * a.width * 4), ((a.y - r.y + y) * r.width + (a.x - r.x)) * 4);
|
|
3323
3281
|
}
|
|
3324
|
-
function
|
|
3325
|
-
|
|
3282
|
+
function workingToSamples(data, depth) {
|
|
3283
|
+
if (depth === 32) return data;
|
|
3284
|
+
const out = new Uint16Array(data.length);
|
|
3285
|
+
for (let i = 0; i < data.length; i++) {
|
|
3286
|
+
const v = data[i];
|
|
3287
|
+
out[i] = v > 0 ? v < 1 ? Math.round(v * 65535) : 65535 : 0;
|
|
3288
|
+
}
|
|
3289
|
+
return out;
|
|
3326
3290
|
}
|
|
3327
|
-
function
|
|
3328
|
-
|
|
3291
|
+
function encodeInPlace(d) {
|
|
3292
|
+
for (let i = 0; i < d.length; i += 4) {
|
|
3293
|
+
d[i] = _chunkOLNIPTB3cjs.srgbEncode.call(void 0, d[i]);
|
|
3294
|
+
d[i + 1] = _chunkOLNIPTB3cjs.srgbEncode.call(void 0, d[i + 1]);
|
|
3295
|
+
d[i + 2] = _chunkOLNIPTB3cjs.srgbEncode.call(void 0, d[i + 2]);
|
|
3296
|
+
}
|
|
3329
3297
|
}
|
|
3330
|
-
function
|
|
3331
|
-
|
|
3332
|
-
|
|
3333
|
-
|
|
3334
|
-
|
|
3335
|
-
|
|
3298
|
+
function decodeInPlace(d) {
|
|
3299
|
+
for (let i = 0; i < d.length; i += 4) {
|
|
3300
|
+
d[i] = _chunkOLNIPTB3cjs.srgbDecode.call(void 0, d[i]);
|
|
3301
|
+
d[i + 1] = _chunkOLNIPTB3cjs.srgbDecode.call(void 0, d[i + 1]);
|
|
3302
|
+
d[i + 2] = _chunkOLNIPTB3cjs.srgbDecode.call(void 0, d[i + 2]);
|
|
3303
|
+
}
|
|
3336
3304
|
}
|
|
3337
|
-
|
|
3305
|
+
|
|
3306
|
+
// src/raster/layers.ts
|
|
3307
|
+
var childrenOf = (l) => l.type === "group" ? _nullishCoalesce(l.children, () => ( null)) : null;
|
|
3308
|
+
function flattenLayers(layers) {
|
|
3338
3309
|
const out = [];
|
|
3339
|
-
|
|
3340
|
-
|
|
3310
|
+
const walk = (list) => {
|
|
3311
|
+
for (const l of list) {
|
|
3312
|
+
out.push(l);
|
|
3313
|
+
const c = childrenOf(l);
|
|
3314
|
+
if (c) walk(c);
|
|
3315
|
+
}
|
|
3316
|
+
};
|
|
3317
|
+
walk(layers);
|
|
3341
3318
|
return out;
|
|
3342
3319
|
}
|
|
3320
|
+
function findLayer(layers, id) {
|
|
3321
|
+
const walk = (list, parent, path) => {
|
|
3322
|
+
for (let i = 0; i < list.length; i++) {
|
|
3323
|
+
const l = list[i];
|
|
3324
|
+
if (l.id === id) return { layer: l, parent, index: i, path };
|
|
3325
|
+
const c = childrenOf(l);
|
|
3326
|
+
if (c) {
|
|
3327
|
+
const g = l;
|
|
3328
|
+
const hit = walk(c, g, [...path, g]);
|
|
3329
|
+
if (hit) return hit;
|
|
3330
|
+
}
|
|
3331
|
+
}
|
|
3332
|
+
return null;
|
|
3333
|
+
};
|
|
3334
|
+
return walk(layers, null, []);
|
|
3335
|
+
}
|
|
3336
|
+
function mapLayer(layers, id, fn) {
|
|
3337
|
+
let changed = false;
|
|
3338
|
+
const walk = (list) => {
|
|
3339
|
+
let out = null;
|
|
3340
|
+
for (let i = 0; i < list.length; i++) {
|
|
3341
|
+
const l = list[i];
|
|
3342
|
+
let next = l;
|
|
3343
|
+
if (l.id === id) {
|
|
3344
|
+
next = fn(l);
|
|
3345
|
+
changed = true;
|
|
3346
|
+
} else {
|
|
3347
|
+
const c = childrenOf(l);
|
|
3348
|
+
if (c) {
|
|
3349
|
+
const children = walk(c);
|
|
3350
|
+
if (children !== c) next = { ...l, children };
|
|
3351
|
+
}
|
|
3352
|
+
}
|
|
3353
|
+
if (next !== l) {
|
|
3354
|
+
if (!out) out = list.slice(0, i);
|
|
3355
|
+
if (next) out.push(next);
|
|
3356
|
+
} else if (out) out.push(l);
|
|
3357
|
+
}
|
|
3358
|
+
return _nullishCoalesce(out, () => ( list));
|
|
3359
|
+
};
|
|
3360
|
+
const result = walk(layers);
|
|
3361
|
+
return changed ? result : layers;
|
|
3362
|
+
}
|
|
3363
|
+
function insertLayer(layers, layer, parentId, index) {
|
|
3364
|
+
const put = (list) => {
|
|
3365
|
+
const at = index === void 0 ? list.length : Math.max(0, Math.min(list.length, index));
|
|
3366
|
+
const next = list.slice();
|
|
3367
|
+
next.splice(at, 0, layer);
|
|
3368
|
+
return next;
|
|
3369
|
+
};
|
|
3370
|
+
if (!parentId) return put(layers);
|
|
3371
|
+
return mapLayer(layers, parentId, (g) => {
|
|
3372
|
+
const c = childrenOf(g);
|
|
3373
|
+
return c ? { ...g, children: put(c) } : g;
|
|
3374
|
+
});
|
|
3375
|
+
}
|
|
3376
|
+
function isLayerLocked(layer, what) {
|
|
3377
|
+
return Boolean(_optionalChain([layer, 'access', _91 => _91.locks, 'optionalAccess', _92 => _92.all]) || _optionalChain([layer, 'access', _93 => _93.locks, 'optionalAccess', _94 => _94[what]]));
|
|
3378
|
+
}
|
|
3343
3379
|
|
|
3344
3380
|
// src/raster/transform.ts
|
|
3345
3381
|
var INTERPOLATIONS = ["nearest", "bilinear", "bicubic"];
|
|
@@ -4218,4 +4254,5 @@ function compositeSurfaceOver(base, top) {
|
|
|
4218
4254
|
|
|
4219
4255
|
|
|
4220
4256
|
|
|
4221
|
-
|
|
4257
|
+
|
|
4258
|
+
exports.DEFAULT_GLOBAL_LIGHT = DEFAULT_GLOBAL_LIGHT; exports.LAYER_EFFECT_KINDS = LAYER_EFFECT_KINDS; exports.layerEffectLabel = layerEffectLabel; exports.isLayerEffectKind = isLayerEffectKind; exports.defaultEffectGradient = defaultEffectGradient; exports.newEffectId = newEffectId; exports.defaultLayerEffect = defaultLayerEffect; exports.hasActiveEffects = hasActiveEffects; exports.MAX_EFFECT_REACH = MAX_EFFECT_REACH; exports.effectReach = effectReach; exports.effectsMargin = effectsMargin; exports.effectsScale = effectsScale; exports.scaleLayerEffect = scaleLayerEffect; exports.parseEffectColor = parseEffectColor; exports.effectColorHex = effectColorHex; exports.LayerEffectError = LayerEffectError; exports.validateEffectGradient = validateEffectGradient; exports.layerEffectFields = layerEffectFields; exports.validateLayerEffect = validateLayerEffect; exports.mergeLayerEffect = mergeLayerEffect; exports.validateLayerEffects = validateLayerEffects; exports.normalizeLayerEffects = normalizeLayerEffects; exports.effectsFingerprint = effectsFingerprint; exports.PatternTile = PatternTile; exports.PatternPlacement = PatternPlacement; exports.builtinPatternIds = builtinPatternIds; exports.builtinPattern = builtinPattern; exports.hashNoise = hashNoise; exports.CURVE_LUT_SIZE = CURVE_LUT_SIZE; exports.curveLut = curveLut; exports.STROKE_CHAMFER_MAX = STROKE_CHAMFER_MAX; exports.contourLut = contourLut; exports.activeEffectItems = activeEffectItems; exports.effectsAreLocal = effectsAreLocal; exports.buildEffectMaps = buildEffectMaps; exports.patchEffectMaps = patchEffectMaps; exports.gradientT = gradientT; exports.effectFillColors = effectFillColors; exports.compositeLayerEffects = compositeLayerEffects; exports.renderLayerEffects = renderLayerEffects; exports.applyEdgeAmbient = applyEdgeAmbient; exports.blendTile = blendTile; exports.RasterCompositor = RasterCompositor; exports.changedTiles = changedTiles; exports.DeepCompositor = DeepCompositor; exports.workingToSamples = workingToSamples; exports.flattenLayers = flattenLayers; exports.findLayer = findLayer; exports.mapLayer = mapLayer; exports.insertLayer = insertLayer; exports.isLayerLocked = isLayerLocked; exports.INTERPOLATIONS = INTERPOLATIONS; exports.isInterpolation = isInterpolation; exports.MAX_TRANSFORM_PIXELS = MAX_TRANSFORM_PIXELS; exports.TransformTooLargeError = TransformTooLargeError; exports.keysWeight = keysWeight; exports.reduceSurface = reduceSurface; exports.transformedBounds = transformedBounds; exports.transformSurface = transformSurface; exports.warpSurface = warpSurface; exports.compositeSurfaceOver = compositeSurfaceOver;
|