@pixerate/editor 0.120.0 → 0.122.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/THIRD_PARTY_NOTICES.md +1 -1
- package/dist/{chunk-HTAFDTNR.cjs → chunk-4PUPGALM.cjs} +251 -156
- package/dist/chunk-4PUPGALM.cjs.map +1 -0
- package/dist/{chunk-N3467VD6.js → chunk-7QN76ESJ.js} +1 -179
- package/dist/chunk-7QN76ESJ.js.map +1 -0
- package/dist/{chunk-UMVW2Q66.js → chunk-CLTTLLWA.js} +1090 -982
- package/dist/chunk-CLTTLLWA.js.map +1 -0
- package/dist/{chunk-EJVDBITD.cjs → chunk-DCLJNVZS.cjs} +2 -180
- package/dist/chunk-DCLJNVZS.cjs.map +1 -0
- package/dist/{chunk-WMRIG4XQ.cjs → chunk-DFFBJV3U.cjs} +1855 -1747
- package/dist/chunk-DFFBJV3U.cjs.map +1 -0
- package/dist/chunk-GX332W2C.js +181 -0
- package/dist/chunk-GX332W2C.js.map +1 -0
- package/dist/{chunk-BOWUU4LJ.js → chunk-IX3YKUVK.js} +105 -10
- package/dist/chunk-IX3YKUVK.js.map +1 -0
- package/dist/{chunk-TS5IEUW6.cjs → chunk-K7V27T72.cjs} +178 -3
- package/dist/chunk-K7V27T72.cjs.map +1 -0
- package/dist/chunk-MUUXNRU4.cjs +181 -0
- package/dist/chunk-MUUXNRU4.cjs.map +1 -0
- package/dist/{chunk-YHW26LS2.js → chunk-ZZPGTNXJ.js} +177 -2
- package/dist/chunk-ZZPGTNXJ.js.map +1 -0
- package/dist/{render-B05K68_h.d.ts → deep-DLwKZDFr.d.ts} +143 -134
- package/dist/{render-DnAbIKcs.d.cts → deep-QS3ppbMX.d.cts} +143 -134
- package/dist/{export-D2D8hb_u.d.ts → export-VmTofKIk.d.ts} +11 -4
- package/dist/{export-fP2hZYjm.d.cts → export-jKKj8Fg8.d.cts} +11 -4
- package/dist/image-editor/index.cjs +760 -734
- package/dist/image-editor/index.cjs.map +1 -1
- package/dist/image-editor/index.d.cts +18 -6
- package/dist/image-editor/index.d.ts +18 -6
- package/dist/image-editor/index.js +37 -11
- package/dist/image-editor/index.js.map +1 -1
- package/dist/paint/index.cjs +22 -2
- package/dist/paint/index.cjs.map +1 -1
- package/dist/paint/index.d.cts +159 -1
- package/dist/paint/index.d.ts +159 -1
- package/dist/paint/index.js +21 -1
- package/dist/paint-editor/index.cjs +95 -94
- package/dist/paint-editor/index.cjs.map +1 -1
- package/dist/paint-editor/index.d.cts +2 -2
- package/dist/paint-editor/index.d.ts +2 -2
- package/dist/paint-editor/index.js +12 -11
- package/dist/paint-editor/index.js.map +1 -1
- package/dist/raster/index.cjs +5 -4
- package/dist/raster/index.cjs.map +1 -1
- package/dist/raster/index.d.cts +29 -7
- package/dist/raster/index.d.ts +29 -7
- package/dist/raster/index.js +11 -10
- package/dist/vector/index.cjs +14 -12
- package/dist/vector/index.cjs.map +1 -1
- package/dist/vector/index.js +7 -5
- package/dist/vector/index.js.map +1 -1
- package/package.json +1 -1
- package/skills/pixerate-canvas/SKILL.md +23 -1
- package/skills/pixerate-image-editor/SKILL.md +7 -1
- package/skills/pixerate-image-editor/references/photoshop-files.md +4 -3
- package/skills/pixerate-paint-editor/SKILL.md +32 -7
- package/dist/chunk-BOWUU4LJ.js.map +0 -1
- package/dist/chunk-EJVDBITD.cjs.map +0 -1
- package/dist/chunk-HTAFDTNR.cjs.map +0 -1
- package/dist/chunk-N3467VD6.js.map +0 -1
- package/dist/chunk-TS5IEUW6.cjs.map +0 -1
- package/dist/chunk-UMVW2Q66.js.map +0 -1
- package/dist/chunk-WMRIG4XQ.cjs.map +0 -1
- package/dist/chunk-YHW26LS2.js.map +0 -1
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
|
|
10
|
-
var
|
|
10
|
+
var _chunkMUUXNRU4cjs = require('./chunk-MUUXNRU4.cjs');
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
|
|
@@ -464,1884 +464,1972 @@ function stableStringify(v) {
|
|
|
464
464
|
return JSON.stringify(v);
|
|
465
465
|
}
|
|
466
466
|
|
|
467
|
-
// src/raster/
|
|
468
|
-
var
|
|
469
|
-
var
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
}
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
/** The composite of `layers` over `rect` as float RGBA in the working space (`rect.width × rect.height × 4`). */
|
|
484
|
-
composite(layers, rect, sources) {
|
|
485
|
-
this.sources = sources;
|
|
486
|
-
const acc = new Float32Array(Math.max(0, rect.width * rect.height * 4));
|
|
487
|
-
if (rect.width > 0 && rect.height > 0) this.runSteps(this.buildSteps(layers), acc, true, rect);
|
|
488
|
-
return acc;
|
|
489
|
-
}
|
|
490
|
-
// --- Steps (as RasterCompositor.buildSteps) ------------------------------------
|
|
491
|
-
isPixel(l) {
|
|
492
|
-
return l.type === "pixel" || (_nullishCoalesce(_optionalChain([this, 'access', _2 => _2.profile, 'access', _3 => _3.isPixelLike, 'optionalCall', _4 => _4(l)]), () => ( false)));
|
|
467
|
+
// src/raster/curve.ts
|
|
468
|
+
var CURVE_LUT_SIZE = 4096;
|
|
469
|
+
var clamp01 = (v) => v <= 0 ? 0 : v >= 1 ? 1 : v;
|
|
470
|
+
function curveLut(points, size = CURVE_LUT_SIZE) {
|
|
471
|
+
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]);
|
|
472
|
+
const dedup = [];
|
|
473
|
+
for (const p of pts) {
|
|
474
|
+
if (dedup.length && Math.abs(dedup[dedup.length - 1][0] - p[0]) < 1e-6) continue;
|
|
475
|
+
dedup.push(p);
|
|
493
476
|
}
|
|
494
|
-
|
|
495
|
-
|
|
477
|
+
const out = new Float32Array(size);
|
|
478
|
+
const n = dedup.length;
|
|
479
|
+
if (n < 2) {
|
|
480
|
+
for (let k = 0; k < size; k++) out[k] = k / (size - 1);
|
|
481
|
+
return out;
|
|
496
482
|
}
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
483
|
+
const x = dedup.map((p) => p[0]);
|
|
484
|
+
const y = dedup.map((p) => p[1]);
|
|
485
|
+
const m2 = new Float64Array(n);
|
|
486
|
+
if (n > 2) {
|
|
487
|
+
const c = new Float64Array(n);
|
|
488
|
+
const d = new Float64Array(n);
|
|
489
|
+
for (let i = 1; i < n - 1; i++) {
|
|
490
|
+
const h0 = x[i] - x[i - 1];
|
|
491
|
+
const h1 = x[i + 1] - x[i];
|
|
492
|
+
const a = h0 / 6;
|
|
493
|
+
const b = (h0 + h1) / 3;
|
|
494
|
+
const cc = h1 / 6;
|
|
495
|
+
const r = (y[i + 1] - y[i]) / h1 - (y[i] - y[i - 1]) / h0;
|
|
496
|
+
const denom = b - a * c[i - 1];
|
|
497
|
+
c[i] = cc / denom;
|
|
498
|
+
d[i] = (r - a * d[i - 1]) / denom;
|
|
510
499
|
}
|
|
511
|
-
|
|
512
|
-
}
|
|
513
|
-
runSteps(steps, acc, empty, r) {
|
|
514
|
-
for (const s of steps) empty = this.runStep(s, acc, empty, r);
|
|
515
|
-
return empty;
|
|
500
|
+
for (let i = n - 2; i >= 1; i--) m2[i] = d[i] - c[i] * m2[i + 1];
|
|
516
501
|
}
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
const layer = step.layer;
|
|
524
|
-
if (!layer.visible) return empty;
|
|
525
|
-
const clipped = step.clipped.filter((l) => l.visible);
|
|
526
|
-
const coverage = this.renderedAlone(layer) ? null : this.base.maskCoverage(layer, r, this.sources);
|
|
527
|
-
if (coverage && coverage.every((v) => v <= 0)) return empty;
|
|
528
|
-
if (step.kind === "group" && !this.renderedAlone(layer)) {
|
|
529
|
-
if (layer.blend === "pass-through" && !clipped.length) {
|
|
530
|
-
if (layer.opacity >= 1 && !coverage) return this.runSteps(step.steps, acc, empty, r);
|
|
531
|
-
const before = acc.slice();
|
|
532
|
-
const stillEmpty = this.runSteps(step.steps, acc, empty, r);
|
|
533
|
-
lerp(acc, before, layer.opacity, coverage);
|
|
534
|
-
return empty && stillEmpty;
|
|
535
|
-
}
|
|
536
|
-
const buf2 = new Float32Array(acc.length);
|
|
537
|
-
if (this.runSteps(step.steps, buf2, true, r)) return empty;
|
|
538
|
-
this.applyClipped(clipped, buf2, r);
|
|
539
|
-
const mode2 = layer.blend === "pass-through" ? "normal" : layer.blend;
|
|
540
|
-
this.blend(acc, buf2, mode2, layer.opacity, coverage);
|
|
541
|
-
return false;
|
|
502
|
+
let seg = 0;
|
|
503
|
+
for (let k = 0; k < size; k++) {
|
|
504
|
+
const xv = k / (size - 1);
|
|
505
|
+
if (xv <= x[0]) {
|
|
506
|
+
out[k] = clamp01(y[0]);
|
|
507
|
+
continue;
|
|
542
508
|
}
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
const fill2 = !alone && this.isPixel(layer) ? _nullishCoalesce(layer.fillOpacity, () => ( 1)) : 1;
|
|
547
|
-
const mode = this.blendOf(layer);
|
|
548
|
-
if (!clipped.length) {
|
|
549
|
-
this.blend(acc, content, mode, layer.opacity * fill2, coverage);
|
|
550
|
-
return false;
|
|
509
|
+
if (xv >= x[n - 1]) {
|
|
510
|
+
out[k] = clamp01(y[n - 1]);
|
|
511
|
+
continue;
|
|
551
512
|
}
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
513
|
+
while (seg < n - 2 && xv > x[seg + 1]) seg++;
|
|
514
|
+
const x0 = x[seg], x1 = x[seg + 1];
|
|
515
|
+
const h = x1 - x0;
|
|
516
|
+
const a = (x1 - xv) / h;
|
|
517
|
+
const b = (xv - x0) / h;
|
|
518
|
+
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;
|
|
519
|
+
out[k] = clamp01(v);
|
|
557
520
|
}
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
if (!src) continue;
|
|
578
|
-
const fill2 = !alone && this.isPixel(c) ? _nullishCoalesce(c.fillOpacity, () => ( 1)) : 1;
|
|
579
|
-
const keep = new Float32Array(buf.length >> 2);
|
|
580
|
-
for (let i = 3, p = 0; i < buf.length; i += 4, p++) keep[p] = buf[i];
|
|
581
|
-
this.blend(buf, src, c.blend === "pass-through" ? "normal" : this.blendOf(c), c.opacity * fill2, coverage);
|
|
582
|
-
for (let i = 3, p = 0; i < buf.length; i += 4, p++) buf[i] = keep[p];
|
|
521
|
+
return out;
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
// src/raster/effects/patterns.ts
|
|
525
|
+
var PatternTile = class {
|
|
526
|
+
|
|
527
|
+
|
|
528
|
+
|
|
529
|
+
constructor(p) {
|
|
530
|
+
this.w = Math.max(1, p.width | 0);
|
|
531
|
+
this.h = Math.max(1, p.height | 0);
|
|
532
|
+
const n = this.w * this.h;
|
|
533
|
+
this.px = new Float32Array(n * 4);
|
|
534
|
+
for (let i = 0; i < n; i++) {
|
|
535
|
+
const a = (_nullishCoalesce(p.data[i * 4 + 3], () => ( 0))) / 255;
|
|
536
|
+
this.px[i * 4] = (_nullishCoalesce(p.data[i * 4], () => ( 0))) / 255 * a;
|
|
537
|
+
this.px[i * 4 + 1] = (_nullishCoalesce(p.data[i * 4 + 1], () => ( 0))) / 255 * a;
|
|
538
|
+
this.px[i * 4 + 2] = (_nullishCoalesce(p.data[i * 4 + 2], () => ( 0))) / 255 * a;
|
|
539
|
+
this.px[i * 4 + 3] = a;
|
|
583
540
|
}
|
|
584
|
-
flush();
|
|
585
541
|
}
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
542
|
+
/** Bilinear wrapping sample at tile coordinates (pixel centres at `i + 0.5`), straight alpha into `out`. */
|
|
543
|
+
sample(u, v, out) {
|
|
544
|
+
u -= 0.5;
|
|
545
|
+
v -= 0.5;
|
|
546
|
+
const x0 = Math.floor(u);
|
|
547
|
+
const y0 = Math.floor(v);
|
|
548
|
+
const fx = u - x0;
|
|
549
|
+
const fy = v - y0;
|
|
550
|
+
let r = 0;
|
|
551
|
+
let g = 0;
|
|
552
|
+
let b = 0;
|
|
553
|
+
let a = 0;
|
|
554
|
+
for (let dy = 0; dy < 2; dy++) {
|
|
555
|
+
const wy2 = dy ? fy : 1 - fy;
|
|
556
|
+
if (wy2 === 0) continue;
|
|
557
|
+
const yi = ((y0 + dy) % this.h + this.h) % this.h;
|
|
558
|
+
for (let dx = 0; dx < 2; dx++) {
|
|
559
|
+
const wx2 = dx ? fx : 1 - fx;
|
|
560
|
+
if (wx2 === 0) continue;
|
|
561
|
+
const xi = ((x0 + dx) % this.w + this.w) % this.w;
|
|
562
|
+
const k = wx2 * wy2;
|
|
563
|
+
const i = (yi * this.w + xi) * 4;
|
|
564
|
+
r += this.px[i] * k;
|
|
565
|
+
g += this.px[i + 1] * k;
|
|
566
|
+
b += this.px[i + 2] * k;
|
|
567
|
+
a += this.px[i + 3] * k;
|
|
595
568
|
}
|
|
596
|
-
visible.push(node);
|
|
597
569
|
}
|
|
598
|
-
if (
|
|
599
|
-
|
|
600
|
-
if (this.linear) mapColour(acc, _chunk7ISPWEJAcjs.srgbEncode);
|
|
601
|
-
this.deep.applyFilterRunDeep(visible, acc, r, masks, this.sources);
|
|
602
|
-
if (this.linear) mapColour(acc, _chunk7ISPWEJAcjs.srgbDecode);
|
|
570
|
+
if (a <= 0) {
|
|
571
|
+
out[0] = out[1] = out[2] = out[3] = 0;
|
|
603
572
|
return;
|
|
604
573
|
}
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
574
|
+
out[0] = r / a;
|
|
575
|
+
out[1] = g / a;
|
|
576
|
+
out[2] = b / a;
|
|
577
|
+
out[3] = Math.min(1, a);
|
|
608
578
|
}
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
579
|
+
};
|
|
580
|
+
var PatternPlacement = class {
|
|
581
|
+
|
|
582
|
+
|
|
583
|
+
|
|
584
|
+
|
|
585
|
+
|
|
586
|
+
/** `anchor`: the layer's top-left (used when `link`); `phase` in px; `scale` a fraction; `angle` degrees counter-clockwise. */
|
|
587
|
+
constructor(anchor, link, phase, scale, angle) {
|
|
588
|
+
const bx = link ? anchor.x : 0;
|
|
589
|
+
const by = link ? anchor.y : 0;
|
|
590
|
+
this.ox = bx + phase.x;
|
|
591
|
+
this.oy = by + phase.y;
|
|
592
|
+
this.inv = Number.isFinite(scale) && scale > 1e-3 ? 1 / scale : 1;
|
|
593
|
+
const a = (Number.isFinite(angle) ? angle : 0) * Math.PI / 180;
|
|
594
|
+
this.c = Math.cos(a);
|
|
595
|
+
this.s = Math.sin(a);
|
|
615
596
|
}
|
|
616
|
-
|
|
617
|
-
|
|
597
|
+
/** Tile coordinates of the document point `(x, y)` into `out[0..1]`. */
|
|
598
|
+
map(x, y, out) {
|
|
599
|
+
const dx = x - this.ox;
|
|
600
|
+
const dy = y - this.oy;
|
|
601
|
+
out[0] = (dx * this.c - dy * this.s) * this.inv;
|
|
602
|
+
out[1] = (dx * this.s + dy * this.c) * this.inv;
|
|
618
603
|
}
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
const samples = _chunk7ISPWEJAcjs.readDeepRegion.call(void 0, surface, { x: r.x - ox, y: r.y - oy, width: r.width, height: r.height }, this.depth);
|
|
631
|
-
if (samples instanceof Float32Array) return samples;
|
|
632
|
-
const out = new Float32Array(samples.length);
|
|
633
|
-
for (let i = 0; i < samples.length; i++) out[i] = samples[i] / 65535;
|
|
634
|
-
return out;
|
|
635
|
-
}
|
|
636
|
-
/** 8-bit RGBA to the working space. */
|
|
637
|
-
from8(bytes) {
|
|
638
|
-
if (this.linear) return _chunk7ISPWEJAcjs.to32From8.call(void 0, bytes, 4);
|
|
639
|
-
const out = new Float32Array(bytes.length);
|
|
640
|
-
for (let i = 0; i < bytes.length; i++) out[i] = bytes[i] / 255;
|
|
641
|
-
return out;
|
|
642
|
-
}
|
|
643
|
-
/** The working space to 8-bit RGBA. */
|
|
644
|
-
to8(acc) {
|
|
645
|
-
const out = new Uint8ClampedArray(acc.length);
|
|
646
|
-
for (let i = 0; i < acc.length; i += 4) {
|
|
647
|
-
for (let c = 0; c < 3; c++) out[i + c] = Math.round((this.linear ? _chunk7ISPWEJAcjs.srgbEncode.call(void 0, acc[i + c]) : acc[i + c]) * 255);
|
|
648
|
-
out[i + 3] = Math.round(acc[i + 3] * 255);
|
|
604
|
+
};
|
|
605
|
+
var BUILTINS = {
|
|
606
|
+
checker: { name: "Checker", size: 16, paint: (x, y) => x < 8 !== y < 8 ? [204, 204, 204, 255] : [255, 255, 255, 255] },
|
|
607
|
+
stripes: { name: "Diagonal Stripes", size: 16, paint: (x, y) => (x + y) % 16 < 8 ? [40, 40, 40, 255] : [235, 235, 235, 255] },
|
|
608
|
+
dots: {
|
|
609
|
+
name: "Dots",
|
|
610
|
+
size: 12,
|
|
611
|
+
paint: (x, y) => {
|
|
612
|
+
const d = Math.hypot(x + 0.5 - 6, y + 0.5 - 6);
|
|
613
|
+
const a = Math.max(0, Math.min(1, 3.5 - d));
|
|
614
|
+
return [Math.round(255 - a * 215), Math.round(255 - a * 215), Math.round(255 - a * 215), 255];
|
|
649
615
|
}
|
|
650
|
-
|
|
651
|
-
}
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
const cb = [0, 0, 0];
|
|
659
|
-
const cs = [0, 0, 0];
|
|
660
|
-
const mix = [0, 0, 0];
|
|
661
|
-
for (let i = 0, p = 0; i < dst.length; i += 4, p++) {
|
|
662
|
-
const sa = src[i + 3];
|
|
663
|
-
if (!(sa > 0)) continue;
|
|
664
|
-
const k = coverage ? alpha * coverage[p] : alpha;
|
|
665
|
-
if (!(k > 0)) continue;
|
|
666
|
-
const as = Math.min(1, sa * k);
|
|
667
|
-
const ab = dst[i + 3];
|
|
668
|
-
const ao = as + ab * (1 - as);
|
|
669
|
-
if (ao <= 0) {
|
|
670
|
-
dst[i] = dst[i + 1] = dst[i + 2] = dst[i + 3] = 0;
|
|
671
|
-
continue;
|
|
672
|
-
}
|
|
673
|
-
if (normal && as >= 1) {
|
|
674
|
-
dst[i] = src[i];
|
|
675
|
-
dst[i + 1] = src[i + 1];
|
|
676
|
-
dst[i + 2] = src[i + 2];
|
|
677
|
-
dst[i + 3] = 1;
|
|
678
|
-
continue;
|
|
679
|
-
}
|
|
680
|
-
for (let c = 0; c < 3; c++) {
|
|
681
|
-
cb[c] = dst[i + c];
|
|
682
|
-
cs[c] = src[i + c];
|
|
683
|
-
}
|
|
684
|
-
if (pigment) {
|
|
685
|
-
if (this.linear) for (let c = 0; c < 3; c++) cb[c] = _chunk7ISPWEJAcjs.srgbEncode.call(void 0, cb[c]), cs[c] = _chunk7ISPWEJAcjs.srgbEncode.call(void 0, cs[c]);
|
|
686
|
-
_chunk7ISPWEJAcjs.mixPigmentRgb.call(void 0, cb, cs, as / ao, mix);
|
|
687
|
-
for (let c = 0; c < 3; c++) dst[i + c] = this.linear ? _chunk7ISPWEJAcjs.srgbDecode.call(void 0, mix[c]) : mix[c];
|
|
688
|
-
dst[i + 3] = ao;
|
|
689
|
-
continue;
|
|
690
|
-
}
|
|
691
|
-
const m = normal ? cs : _chunk7ISPWEJAcjs.blendRgb.call(void 0, mode, cb, cs);
|
|
692
|
-
const wb = (1 - as) * ab;
|
|
693
|
-
const ws = (1 - ab) * as;
|
|
694
|
-
const wm = as * ab;
|
|
695
|
-
for (let c = 0; c < 3; c++) dst[i + c] = (wb * cb[c] + ws * cs[c] + wm * m[c]) / ao;
|
|
696
|
-
dst[i + 3] = ao;
|
|
616
|
+
},
|
|
617
|
+
grid: { name: "Grid", size: 16, paint: (x, y) => x === 0 || y === 0 ? [90, 90, 90, 255] : [250, 250, 250, 255] },
|
|
618
|
+
noise: {
|
|
619
|
+
name: "Noise",
|
|
620
|
+
size: 64,
|
|
621
|
+
paint: (x, y) => {
|
|
622
|
+
const v = Math.round(hashNoise(x, y) * 255);
|
|
623
|
+
return [v, v, v, 255];
|
|
697
624
|
}
|
|
698
625
|
}
|
|
699
626
|
};
|
|
700
|
-
function
|
|
701
|
-
|
|
702
|
-
const k = coverage ? alpha * coverage[p] : alpha;
|
|
703
|
-
if (k >= 1) continue;
|
|
704
|
-
for (let c = 0; c < 4; c++) dst[i + c] = before[i + c] + (dst[i + c] - before[i + c]) * k;
|
|
705
|
-
}
|
|
627
|
+
function builtinPatternIds() {
|
|
628
|
+
return Object.keys(BUILTINS);
|
|
706
629
|
}
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
630
|
+
var builtinCache = /* @__PURE__ */ new Map();
|
|
631
|
+
function builtinPattern(id) {
|
|
632
|
+
const def = BUILTINS[id];
|
|
633
|
+
if (!def) return null;
|
|
634
|
+
let p = builtinCache.get(id);
|
|
635
|
+
if (!p) {
|
|
636
|
+
const data = new Uint8ClampedArray(def.size * def.size * 4);
|
|
637
|
+
for (let y = 0; y < def.size; y++) {
|
|
638
|
+
for (let x = 0; x < def.size; x++) data.set(def.paint(x, y), (y * def.size + x) * 4);
|
|
639
|
+
}
|
|
640
|
+
p = { id, name: def.name, width: def.size, height: def.size, data };
|
|
641
|
+
builtinCache.set(id, p);
|
|
712
642
|
}
|
|
643
|
+
return p;
|
|
713
644
|
}
|
|
714
|
-
function
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
}
|
|
721
|
-
return out;
|
|
645
|
+
function hashNoise(x, y) {
|
|
646
|
+
let h = Math.imul(x | 0, 2376512323) ^ Math.imul(y | 0, 3625334849) ^ 2654435769;
|
|
647
|
+
h ^= h >>> 15;
|
|
648
|
+
h = Math.imul(h, 739982445);
|
|
649
|
+
h ^= h >>> 12;
|
|
650
|
+
return (h & 65535) / 65536;
|
|
722
651
|
}
|
|
723
652
|
|
|
724
|
-
// src/raster/
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
653
|
+
// src/raster/effects/render.ts
|
|
654
|
+
var INSIDE_EPS = 0.5 / 255;
|
|
655
|
+
var INF = 1e20;
|
|
656
|
+
var FAR = 1e9;
|
|
657
|
+
var STROKE_CHAMFER_MAX = 20;
|
|
658
|
+
var BEVEL_H_EPS = 1e-5;
|
|
659
|
+
var fmap = (w, h, fill2 = 0) => {
|
|
660
|
+
const v = new Float32Array(w * h);
|
|
661
|
+
if (fill2) v.fill(fill2);
|
|
662
|
+
return { w, h, v };
|
|
663
|
+
};
|
|
664
|
+
var clamp = (v, lo, hi) => v < lo ? lo : v > hi ? hi : v;
|
|
665
|
+
var clamp012 = (v) => v <= 0 ? 0 : v >= 1 ? 1 : v;
|
|
666
|
+
function mapGet(m, x, y) {
|
|
667
|
+
return x < 0 || y < 0 || x >= m.w || y >= m.h ? 0 : m.v[y * m.w + x];
|
|
668
|
+
}
|
|
669
|
+
function shifted(m, dx, dy, outside) {
|
|
670
|
+
const reach = (d) => Number.isFinite(d) ? clamp(d, -1e9, 1e9) : 0;
|
|
671
|
+
dx = reach(dx);
|
|
672
|
+
dy = reach(dy);
|
|
673
|
+
const fx = Math.floor(dx);
|
|
674
|
+
const fy = Math.floor(dy);
|
|
675
|
+
const ax = dx - fx;
|
|
676
|
+
const ay = dy - fy;
|
|
677
|
+
const { w, h, v } = m;
|
|
678
|
+
const s = (x, y) => x < 0 || y < 0 || x >= w || y >= h ? outside : v[y * w + x];
|
|
679
|
+
const out = fmap(w, h);
|
|
680
|
+
for (let y = 0; y < h; y++) {
|
|
681
|
+
const sy = y - fy;
|
|
682
|
+
for (let x = 0; x < w; x++) {
|
|
683
|
+
const sx = x - fx;
|
|
684
|
+
const top = s(sx, sy) * (1 - ax) + s(sx - 1, sy) * ax;
|
|
685
|
+
const bot = s(sx, sy - 1) * (1 - ax) + s(sx - 1, sy - 1) * ax;
|
|
686
|
+
out.v[y * w + x] = top * (1 - ay) + bot * ay;
|
|
687
|
+
}
|
|
733
688
|
}
|
|
734
|
-
|
|
735
|
-
return k;
|
|
689
|
+
return out;
|
|
736
690
|
}
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
let wl = Math.floor(wIdeal);
|
|
742
|
-
if (wl % 2 === 0) wl--;
|
|
743
|
-
const wu = wl + 2;
|
|
744
|
-
const mIdeal = (12 * sigma * sigma - n * wl * wl - 4 * n * wl - 3 * n) / (-4 * wl - 4);
|
|
745
|
-
const m = Math.round(mIdeal);
|
|
746
|
-
const sizes = [0, 1, 2].map((i) => i < m ? wl : wu);
|
|
747
|
-
return sizes.map((s) => (s - 1) / 2);
|
|
691
|
+
function mapped(m, f) {
|
|
692
|
+
const out = fmap(m.w, m.h);
|
|
693
|
+
for (let i = 0; i < m.v.length; i++) out.v[i] = f(m.v[i]);
|
|
694
|
+
return out;
|
|
748
695
|
}
|
|
749
|
-
function
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
696
|
+
function dt1(f, n, out, near, v, z) {
|
|
697
|
+
let k = 0;
|
|
698
|
+
v[0] = 0;
|
|
699
|
+
z[0] = -Infinity;
|
|
700
|
+
z[1] = Infinity;
|
|
701
|
+
for (let q = 1; q < n; q++) {
|
|
702
|
+
for (; ; ) {
|
|
703
|
+
const p = v[k];
|
|
704
|
+
const s = (f[q] + q * q - (f[p] + p * p)) / (2 * q - 2 * p);
|
|
705
|
+
if (s <= z[k] && k > 0) {
|
|
706
|
+
k--;
|
|
707
|
+
continue;
|
|
759
708
|
}
|
|
760
|
-
|
|
709
|
+
if (s <= z[k]) {
|
|
710
|
+
v[0] = q;
|
|
711
|
+
z[0] = -Infinity;
|
|
712
|
+
z[1] = Infinity;
|
|
713
|
+
break;
|
|
714
|
+
}
|
|
715
|
+
k++;
|
|
716
|
+
v[k] = q;
|
|
717
|
+
z[k] = s;
|
|
718
|
+
z[k + 1] = Infinity;
|
|
719
|
+
break;
|
|
761
720
|
}
|
|
762
|
-
dst[i] = a;
|
|
763
721
|
}
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
722
|
+
k = 0;
|
|
723
|
+
for (let q = 0; q < n; q++) {
|
|
724
|
+
while (z[k + 1] < q) k++;
|
|
725
|
+
const p = v[k];
|
|
726
|
+
const d = q - p;
|
|
727
|
+
out[q] = d * d + f[p];
|
|
728
|
+
near[q] = p;
|
|
771
729
|
}
|
|
772
|
-
let from = a;
|
|
773
|
-
let to = b;
|
|
774
|
-
for (const r of radii) {
|
|
775
|
-
let sum = 0;
|
|
776
|
-
for (let i = 0; i <= Math.min(r, plen - 1); i++) sum += from[i];
|
|
777
|
-
const k = 2 * r + 1;
|
|
778
|
-
for (let i = 0; i < plen; i++) {
|
|
779
|
-
to[i] = sum / k;
|
|
780
|
-
const add = i + r + 1;
|
|
781
|
-
const drop = i - r;
|
|
782
|
-
if (add < plen) sum += from[add];
|
|
783
|
-
if (drop >= 0) sum -= from[drop];
|
|
784
|
-
}
|
|
785
|
-
const t = from;
|
|
786
|
-
from = to;
|
|
787
|
-
to = t;
|
|
788
|
-
}
|
|
789
|
-
for (let i = 0; i < len; i++) dst[i] = from[i + pad];
|
|
790
730
|
}
|
|
791
|
-
function
|
|
792
|
-
const
|
|
793
|
-
|
|
794
|
-
const
|
|
795
|
-
const
|
|
796
|
-
const
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
const b = new Float32Array(plen);
|
|
805
|
-
passes.push((buf, off, stride, len) => boxesLine(buf, off, stride, len, radii, edge, a, b, line));
|
|
806
|
-
}
|
|
807
|
-
for (const pass of passes) {
|
|
731
|
+
function edtNearest(inside, w, h) {
|
|
732
|
+
const total = w * h;
|
|
733
|
+
const n = Math.max(w, h);
|
|
734
|
+
const f = new Float64Array(n);
|
|
735
|
+
const o = new Float64Array(n);
|
|
736
|
+
const nr = new Int32Array(n);
|
|
737
|
+
const v = new Int32Array(n);
|
|
738
|
+
const z = new Float64Array(n + 1);
|
|
739
|
+
const gc = new Float64Array(total);
|
|
740
|
+
const nc = new Int32Array(total);
|
|
741
|
+
for (let x = 0; x < w; x++) {
|
|
742
|
+
for (let y = 0; y < h; y++) f[y] = inside[y * w + x] ? 0 : INF;
|
|
743
|
+
dt1(f, h, o, nr, v, z);
|
|
808
744
|
for (let y = 0; y < h; y++) {
|
|
809
|
-
|
|
810
|
-
|
|
745
|
+
gc[x * h + y] = o[y];
|
|
746
|
+
nc[x * h + y] = nr[y];
|
|
811
747
|
}
|
|
812
748
|
}
|
|
813
|
-
|
|
749
|
+
const d = new Float32Array(total);
|
|
750
|
+
const near = new Int32Array(total);
|
|
751
|
+
for (let y = 0; y < h; y++) {
|
|
752
|
+
for (let x = 0; x < w; x++) f[x] = gc[x * h + y];
|
|
753
|
+
dt1(f, w, o, nr, v, z);
|
|
814
754
|
for (let x = 0; x < w; x++) {
|
|
815
|
-
|
|
816
|
-
|
|
755
|
+
d[y * w + x] = Math.sqrt(o[x]);
|
|
756
|
+
const px = nr[x];
|
|
757
|
+
near[y * w + x] = nc[px * h + y] * w + px;
|
|
817
758
|
}
|
|
818
759
|
}
|
|
819
|
-
return
|
|
760
|
+
return { d, near };
|
|
820
761
|
}
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
var
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
762
|
+
var S2 = Math.SQRT2;
|
|
763
|
+
var S5 = 2.236068;
|
|
764
|
+
var FWD = [
|
|
765
|
+
[-1, 0, 1],
|
|
766
|
+
[-1, -1, S2],
|
|
767
|
+
[0, -1, 1],
|
|
768
|
+
[1, -1, S2],
|
|
769
|
+
[-1, -2, S5],
|
|
770
|
+
[1, -2, S5],
|
|
771
|
+
[-2, -1, S5],
|
|
772
|
+
[2, -1, S5]
|
|
773
|
+
];
|
|
774
|
+
function chamferFrom(d, w, h) {
|
|
775
|
+
const ox = FWD.map((f) => f[0]);
|
|
776
|
+
const oy = FWD.map((f) => f[1]);
|
|
777
|
+
const wt = FWD.map((f) => f[2]);
|
|
778
|
+
const k = FWD.length;
|
|
779
|
+
for (let pass = 0; pass < 2; pass++) {
|
|
780
|
+
const sign = pass === 0 ? 1 : -1;
|
|
781
|
+
for (let yy = 0; yy < h; yy++) {
|
|
782
|
+
const y = pass === 0 ? yy : h - 1 - yy;
|
|
783
|
+
for (let xx = 0; xx < w; xx++) {
|
|
784
|
+
const x = pass === 0 ? xx : w - 1 - xx;
|
|
785
|
+
const i = y * w + x;
|
|
786
|
+
let best = d[i];
|
|
787
|
+
for (let j = 0; j < k; j++) {
|
|
788
|
+
const nx = x + ox[j] * sign;
|
|
789
|
+
const ny = y + oy[j] * sign;
|
|
790
|
+
if (nx < 0 || ny < 0 || nx >= w || ny >= h) continue;
|
|
791
|
+
const c = d[ny * w + nx] + wt[j];
|
|
792
|
+
if (c < best) best = c;
|
|
793
|
+
}
|
|
794
|
+
d[i] = best;
|
|
795
|
+
}
|
|
831
796
|
}
|
|
832
|
-
}
|
|
833
|
-
|
|
797
|
+
}
|
|
798
|
+
return d;
|
|
799
|
+
}
|
|
800
|
+
function distOutside(s, chamfer) {
|
|
801
|
+
const { w, h, v } = s;
|
|
802
|
+
const n = v.length;
|
|
803
|
+
const out = new Float32Array(n);
|
|
804
|
+
if (chamfer) {
|
|
805
|
+
const start = new Float32Array(n);
|
|
806
|
+
for (let i = 0; i < n; i++) start[i] = v[i] > INSIDE_EPS ? 1 - Math.min(v[i], 1) : INF;
|
|
807
|
+
const d2 = chamferFrom(start, w, h);
|
|
808
|
+
for (let i = 0; i < n; i++) out[i] = v[i] > INSIDE_EPS ? -0.5 : d2[i] - 0.5;
|
|
809
|
+
return out;
|
|
810
|
+
}
|
|
811
|
+
const inside = new Uint8Array(n);
|
|
812
|
+
for (let i = 0; i < n; i++) inside[i] = v[i] > INSIDE_EPS ? 1 : 0;
|
|
813
|
+
const { d, near } = edtNearest(inside, w, h);
|
|
814
|
+
for (let i = 0; i < n; i++) out[i] = inside[i] ? -0.5 : d[i] - 0.5 + (1 - Math.min(v[near[i]], 1));
|
|
834
815
|
return out;
|
|
835
816
|
}
|
|
836
|
-
function
|
|
837
|
-
const
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
if (hit) return hit;
|
|
846
|
-
}
|
|
817
|
+
function localCoverage(s) {
|
|
818
|
+
const out = { w: s.w, h: s.h, v: new Float32Array(s.v) };
|
|
819
|
+
for (let y = 0; y < s.h; y++) {
|
|
820
|
+
for (let x = 0; x < s.w; x++) {
|
|
821
|
+
const a = s.v[y * s.w + x];
|
|
822
|
+
if (a <= INSIDE_EPS) continue;
|
|
823
|
+
let mx = a;
|
|
824
|
+
for (let dy = -1; dy <= 1; dy++) for (let dx = -1; dx <= 1; dx++) mx = Math.max(mx, mapGet(s, x + dx, y + dy));
|
|
825
|
+
out.v[y * s.w + x] = Math.min(a / mx, 1);
|
|
847
826
|
}
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
return walk(layers, null, []);
|
|
827
|
+
}
|
|
828
|
+
return out;
|
|
851
829
|
}
|
|
852
|
-
function
|
|
853
|
-
|
|
854
|
-
const
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
830
|
+
function distInside(s, chamfer) {
|
|
831
|
+
const { w, h, v } = s;
|
|
832
|
+
const n = v.length;
|
|
833
|
+
const out = new Float32Array(n);
|
|
834
|
+
if (chamfer) {
|
|
835
|
+
const cov = localCoverage(s);
|
|
836
|
+
const start = new Float32Array(n);
|
|
837
|
+
for (let i = 0; i < n; i++) start[i] = v[i] <= INSIDE_EPS ? 0 : cov.v[i] < 1 - INSIDE_EPS ? cov.v[i] : INF;
|
|
838
|
+
const d2 = chamferFrom(start, w, h);
|
|
839
|
+
for (let i = 0; i < n; i++) out[i] = v[i] <= INSIDE_EPS ? -0.5 : d2[i] - 0.5;
|
|
840
|
+
return out;
|
|
841
|
+
}
|
|
842
|
+
const outside = new Uint8Array(n);
|
|
843
|
+
for (let i = 0; i < n; i++) outside[i] = v[i] <= INSIDE_EPS ? 1 : 0;
|
|
844
|
+
const { d } = edtNearest(outside, w, h);
|
|
845
|
+
for (let i = 0; i < n; i++) out[i] = outside[i] ? -0.5 : d[i] - 0.5;
|
|
846
|
+
return out;
|
|
847
|
+
}
|
|
848
|
+
function edgeDistances(s, reach) {
|
|
849
|
+
const { w, h, v } = s;
|
|
850
|
+
const n = v.length;
|
|
851
|
+
const edge = new Uint8Array(n);
|
|
852
|
+
const inside = new Uint8Array(n);
|
|
853
|
+
for (let y = 0; y < h; y++) {
|
|
854
|
+
for (let x = 0; x < w; x++) {
|
|
855
|
+
const i = y * w + x;
|
|
856
|
+
const a = v[i];
|
|
857
|
+
if (a <= INSIDE_EPS) continue;
|
|
858
|
+
inside[i] = 1;
|
|
859
|
+
if (a < 1 - INSIDE_EPS || mapGet(s, x - 1, y) <= INSIDE_EPS || mapGet(s, x + 1, y) <= INSIDE_EPS || mapGet(s, x, y - 1) <= INSIDE_EPS || mapGet(s, x, y + 1) <= INSIDE_EPS) edge[i] = 1;
|
|
860
|
+
}
|
|
861
|
+
}
|
|
862
|
+
const { d, near } = edtNearest(edge, w, h);
|
|
863
|
+
const din = new Float32Array(n);
|
|
864
|
+
const dout = new Float32Array(n);
|
|
865
|
+
for (let y = 0; y < h; y++) {
|
|
866
|
+
for (let x = 0; x < w; x++) {
|
|
867
|
+
const i = y * w + x;
|
|
868
|
+
const q = near[i];
|
|
869
|
+
let sd;
|
|
870
|
+
if (d[i] > reach || d[i] >= INF / 2) {
|
|
871
|
+
sd = inside[i] ? -(d[i] + 0.5) : d[i] - 0.5;
|
|
862
872
|
} else {
|
|
863
|
-
const
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
873
|
+
const qx = q % w;
|
|
874
|
+
const qy = (q - qx) / w;
|
|
875
|
+
const g = (dx, dy) => mapGet(s, qx + dx, qy + dy);
|
|
876
|
+
let nx = -(g(1, -1) + 2 * g(1, 0) + g(1, 1) - g(-1, -1) - 2 * g(-1, 0) - g(-1, 1));
|
|
877
|
+
let ny = -(g(-1, 1) + 2 * g(0, 1) + g(1, 1) - g(-1, -1) - 2 * g(0, -1) - g(1, -1));
|
|
878
|
+
const len = Math.hypot(nx, ny);
|
|
879
|
+
if (len > 1e-6) {
|
|
880
|
+
nx /= len;
|
|
881
|
+
ny /= len;
|
|
882
|
+
} else if (d[i] > 0) {
|
|
883
|
+
nx = (x - qx) / d[i];
|
|
884
|
+
ny = (y - qy) / d[i];
|
|
885
|
+
} else {
|
|
886
|
+
nx = 1;
|
|
887
|
+
ny = 0;
|
|
867
888
|
}
|
|
889
|
+
sd = (x - qx) * nx + (y - qy) * ny - (Math.min(v[q], 1) - 0.5);
|
|
868
890
|
}
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
if (next) out.push(next);
|
|
872
|
-
} else if (out) out.push(l);
|
|
891
|
+
din[i] = inside[i] ? Math.max(-sd, inside[i] && !edge[i] ? 0.5 : -0.5) : -0.5;
|
|
892
|
+
dout[i] = inside[i] && !edge[i] ? -0.5 : Math.max(sd, -0.5);
|
|
873
893
|
}
|
|
874
|
-
|
|
875
|
-
};
|
|
876
|
-
const result = walk(layers);
|
|
877
|
-
return changed ? result : layers;
|
|
894
|
+
}
|
|
895
|
+
return { din, dout };
|
|
878
896
|
}
|
|
879
|
-
function
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
return
|
|
888
|
-
const c = childrenOf(g);
|
|
889
|
-
return c ? { ...g, children: put(c) } : g;
|
|
890
|
-
});
|
|
897
|
+
function dilate(s, r) {
|
|
898
|
+
if (!(r > 0)) return s;
|
|
899
|
+
const d = distOutside(s, true);
|
|
900
|
+
const out = { w: s.w, h: s.h, v: new Float32Array(s.v) };
|
|
901
|
+
for (let i = 0; i < d.length; i++) {
|
|
902
|
+
const o = out.v[i];
|
|
903
|
+
out.v[i] = d[i] < 0 ? Math.min(o + r, 1) : Math.max(o, clamp012(r + 0.5 - d[i]));
|
|
904
|
+
}
|
|
905
|
+
return out;
|
|
891
906
|
}
|
|
892
|
-
function
|
|
893
|
-
return
|
|
907
|
+
function boxWidth(w) {
|
|
908
|
+
return Number.isNaN(w) ? 1 : clamp(w, 1, MAX_EFFECT_REACH);
|
|
894
909
|
}
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
this.px[i * 4 + 1] = (_nullishCoalesce(p.data[i * 4 + 1], () => ( 0))) / 255 * a;
|
|
910
|
-
this.px[i * 4 + 2] = (_nullishCoalesce(p.data[i * 4 + 2], () => ( 0))) / 255 * a;
|
|
911
|
-
this.px[i * 4 + 3] = a;
|
|
912
|
-
}
|
|
910
|
+
function boxGeom(bw) {
|
|
911
|
+
bw = boxWidth(bw);
|
|
912
|
+
const half = bw / 2;
|
|
913
|
+
const r = Math.max(0, Math.ceil(half - 0.5));
|
|
914
|
+
const f = clamp012(half - (r - 0.5));
|
|
915
|
+
return [r, f, 1 / bw];
|
|
916
|
+
}
|
|
917
|
+
function boxLine(src, x0, dst, bw) {
|
|
918
|
+
const n = src.length;
|
|
919
|
+
const [r, f, norm] = boxGeom(bw);
|
|
920
|
+
const at = (i) => i >= 0 && i < n ? src[i] : 0;
|
|
921
|
+
if (r === 0) {
|
|
922
|
+
for (let k = 0; k < dst.length; k++) dst[k] = at(x0 + k);
|
|
923
|
+
return;
|
|
913
924
|
}
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
const fx = u - x0;
|
|
921
|
-
const fy = v - y0;
|
|
922
|
-
let r = 0;
|
|
923
|
-
let g = 0;
|
|
924
|
-
let b = 0;
|
|
925
|
-
let a = 0;
|
|
926
|
-
for (let dy = 0; dy < 2; dy++) {
|
|
927
|
-
const wy2 = dy ? fy : 1 - fy;
|
|
928
|
-
if (wy2 === 0) continue;
|
|
929
|
-
const yi = ((y0 + dy) % this.h + this.h) % this.h;
|
|
930
|
-
for (let dx = 0; dx < 2; dx++) {
|
|
931
|
-
const wx2 = dx ? fx : 1 - fx;
|
|
932
|
-
if (wx2 === 0) continue;
|
|
933
|
-
const xi = ((x0 + dx) % this.w + this.w) % this.w;
|
|
934
|
-
const k = wx2 * wy2;
|
|
935
|
-
const i = (yi * this.w + xi) * 4;
|
|
936
|
-
r += this.px[i] * k;
|
|
937
|
-
g += this.px[i + 1] * k;
|
|
938
|
-
b += this.px[i + 2] * k;
|
|
939
|
-
a += this.px[i + 3] * k;
|
|
940
|
-
}
|
|
941
|
-
}
|
|
942
|
-
if (a <= 0) {
|
|
943
|
-
out[0] = out[1] = out[2] = out[3] = 0;
|
|
944
|
-
return;
|
|
945
|
-
}
|
|
946
|
-
out[0] = r / a;
|
|
947
|
-
out[1] = g / a;
|
|
948
|
-
out[2] = b / a;
|
|
949
|
-
out[3] = Math.min(1, a);
|
|
925
|
+
let inner = 0;
|
|
926
|
+
for (let i = x0 - (r - 1); i <= x0 + (r - 1); i++) inner += at(i);
|
|
927
|
+
for (let k = 0; k < dst.length; k++) {
|
|
928
|
+
const x = x0 + k;
|
|
929
|
+
dst[k] = (inner + f * (at(x - r) + at(x + r))) * norm;
|
|
930
|
+
inner += at(x + r) - at(x - r + 1);
|
|
950
931
|
}
|
|
951
|
-
}
|
|
952
|
-
var
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
this.inv = Number.isFinite(scale) && scale > 1e-3 ? 1 / scale : 1;
|
|
965
|
-
const a = (Number.isFinite(angle) ? angle : 0) * Math.PI / 180;
|
|
966
|
-
this.c = Math.cos(a);
|
|
967
|
-
this.s = Math.sin(a);
|
|
932
|
+
}
|
|
933
|
+
var BLUR_EPS = 1e-7;
|
|
934
|
+
var BLUR_FIX = 2 ** 32;
|
|
935
|
+
function tentLine(src, dst, bw, mid) {
|
|
936
|
+
const [r] = boxGeom(bw);
|
|
937
|
+
const m = mid.subarray(0, src.length + 2 * r);
|
|
938
|
+
for (let i = 0; i < src.length; i++) src[i] = Math.round(src[i] * BLUR_FIX);
|
|
939
|
+
boxLine(src, -r, m, bw);
|
|
940
|
+
for (let i = 0; i < m.length; i++) m[i] = Math.round(m[i]);
|
|
941
|
+
boxLine(m, r, dst, bw);
|
|
942
|
+
for (let i = 0; i < dst.length; i++) {
|
|
943
|
+
const v = dst[i] / BLUR_FIX;
|
|
944
|
+
dst[i] = Math.abs(v) < BLUR_EPS ? 0 : v;
|
|
968
945
|
}
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
946
|
+
}
|
|
947
|
+
function tent(m, w) {
|
|
948
|
+
if (!Number.isFinite(w) || m.v.length === 0) return;
|
|
949
|
+
if (boxGeom(w)[0] === 0) return;
|
|
950
|
+
const { w: mw, h: mh } = m;
|
|
951
|
+
const r = boxGeom(w)[0];
|
|
952
|
+
const mid = new Float64Array(Math.max(mw, mh) + 2 * r);
|
|
953
|
+
const row = new Float64Array(mw);
|
|
954
|
+
const rowOut = new Float64Array(mw);
|
|
955
|
+
for (let y = 0; y < mh; y++) {
|
|
956
|
+
for (let x = 0; x < mw; x++) row[x] = m.v[y * mw + x];
|
|
957
|
+
tentLine(row, rowOut, w, mid);
|
|
958
|
+
for (let x = 0; x < mw; x++) m.v[y * mw + x] = rowOut[x];
|
|
975
959
|
}
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
size: 12,
|
|
983
|
-
paint: (x, y) => {
|
|
984
|
-
const d = Math.hypot(x + 0.5 - 6, y + 0.5 - 6);
|
|
985
|
-
const a = Math.max(0, Math.min(1, 3.5 - d));
|
|
986
|
-
return [Math.round(255 - a * 215), Math.round(255 - a * 215), Math.round(255 - a * 215), 255];
|
|
987
|
-
}
|
|
988
|
-
},
|
|
989
|
-
grid: { name: "Grid", size: 16, paint: (x, y) => x === 0 || y === 0 ? [90, 90, 90, 255] : [250, 250, 250, 255] },
|
|
990
|
-
noise: {
|
|
991
|
-
name: "Noise",
|
|
992
|
-
size: 64,
|
|
993
|
-
paint: (x, y) => {
|
|
994
|
-
const v = Math.round(hashNoise(x, y) * 255);
|
|
995
|
-
return [v, v, v, 255];
|
|
996
|
-
}
|
|
960
|
+
const col = new Float64Array(mh);
|
|
961
|
+
const colOut = new Float64Array(mh);
|
|
962
|
+
for (let x = 0; x < mw; x++) {
|
|
963
|
+
for (let y = 0; y < mh; y++) col[y] = m.v[y * mw + x];
|
|
964
|
+
tentLine(col, colOut, w, mid);
|
|
965
|
+
for (let y = 0; y < mh; y++) m.v[y * mw + x] = colOut[y];
|
|
997
966
|
}
|
|
998
|
-
};
|
|
999
|
-
function builtinPatternIds() {
|
|
1000
|
-
return Object.keys(BUILTINS);
|
|
1001
967
|
}
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
if (!
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
968
|
+
function blur(m, size) {
|
|
969
|
+
if (Number.isFinite(size)) tent(m, size);
|
|
970
|
+
}
|
|
971
|
+
var lutCache = /* @__PURE__ */ new WeakMap();
|
|
972
|
+
function contourLut(c) {
|
|
973
|
+
if (!c) return null;
|
|
974
|
+
const cached = lutCache.get(c);
|
|
975
|
+
if (cached !== void 0) return cached;
|
|
976
|
+
const pts = c.points;
|
|
977
|
+
const linear = pts.length === 2 && pts[0].input === 0 && pts[0].output === 0 && pts[1].input === 1 && pts[1].output === 1;
|
|
978
|
+
let lut = null;
|
|
979
|
+
if (pts.length >= 2 && !linear) {
|
|
980
|
+
if (!pts.some((p) => p.corner)) lut = curveLut(pts);
|
|
981
|
+
else {
|
|
982
|
+
const sorted = [...pts].sort((a, b) => a.input - b.input);
|
|
983
|
+
let start = 0;
|
|
984
|
+
for (let i = 1; i < sorted.length; i++) {
|
|
985
|
+
if (!(sorted[i].corner || i === sorted.length - 1)) continue;
|
|
986
|
+
const seg = sorted.slice(start, i + 1);
|
|
987
|
+
const from = seg[0].input;
|
|
988
|
+
const part = curveLut(seg);
|
|
989
|
+
if (!lut) lut = part;
|
|
990
|
+
else for (let k = 0; k < part.length; k++) if (k / (part.length - 1) >= from) lut[k] = part[k];
|
|
991
|
+
start = i;
|
|
992
|
+
}
|
|
993
|
+
lut ??= curveLut(pts);
|
|
1011
994
|
}
|
|
1012
|
-
p = { id, name: def.name, width: def.size, height: def.size, data };
|
|
1013
|
-
builtinCache.set(id, p);
|
|
1014
995
|
}
|
|
1015
|
-
|
|
996
|
+
lutCache.set(c, lut);
|
|
997
|
+
return lut;
|
|
1016
998
|
}
|
|
1017
|
-
function
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
return (h & 65535) / 65536;
|
|
999
|
+
function lutAt(l, v) {
|
|
1000
|
+
const x = clamp012(v) * (l.length - 1);
|
|
1001
|
+
const i = Math.floor(x);
|
|
1002
|
+
const j = Math.min(i + 1, l.length - 1);
|
|
1003
|
+
return l[i] + (l[j] - l[i]) * (x - i);
|
|
1023
1004
|
}
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
const
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1005
|
+
function applyLut(m, l) {
|
|
1006
|
+
return l ? mapped(m, (v) => lutAt(l, v)) : m;
|
|
1007
|
+
}
|
|
1008
|
+
function rangedLut(c, range) {
|
|
1009
|
+
const base = contourLut(c);
|
|
1010
|
+
const r = Number.isFinite(range) ? clamp(range, 0.01, 1) : 1;
|
|
1011
|
+
if (r >= 0.999) return base;
|
|
1012
|
+
const n = 4096;
|
|
1013
|
+
const out = new Float32Array(n);
|
|
1014
|
+
for (let k = 0; k < n; k++) {
|
|
1015
|
+
const v = Math.min(k / (n - 1) / r, 1);
|
|
1016
|
+
out[k] = base ? lutAt(base, v) : v;
|
|
1034
1017
|
}
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1018
|
+
return out;
|
|
1019
|
+
}
|
|
1020
|
+
function satinLut(c) {
|
|
1021
|
+
const lut = contourLut(c);
|
|
1022
|
+
if (!lut) return null;
|
|
1023
|
+
const end = lut[lut.length - 1];
|
|
1024
|
+
const out = new Float32Array(lut.length);
|
|
1025
|
+
for (let k = 0; k < lut.length; k++) out[k] = Math.abs(lut[lut.length - 1 - k] - end);
|
|
1026
|
+
return out;
|
|
1027
|
+
}
|
|
1028
|
+
function noise(m, amount, x0, y0) {
|
|
1029
|
+
if (!Number.isFinite(amount) || amount <= 0) return;
|
|
1030
|
+
for (let y = 0; y < m.h; y++) {
|
|
1031
|
+
for (let x = 0; x < m.w; x++) {
|
|
1032
|
+
const i = y * m.w + x;
|
|
1033
|
+
if (m.v[i] <= BLUR_EPS) continue;
|
|
1034
|
+
m.v[i] = clamp012(m.v[i] + (hashNoise(x0 + x, y0 + y) - 0.5) * 2 * amount);
|
|
1035
|
+
}
|
|
1040
1036
|
}
|
|
1041
|
-
const x = dedup.map((p) => p[0]);
|
|
1042
|
-
const y = dedup.map((p) => p[1]);
|
|
1043
|
-
const m2 = new Float64Array(n);
|
|
1044
|
-
if (n > 2) {
|
|
1045
|
-
const c = new Float64Array(n);
|
|
1046
|
-
const d = new Float64Array(n);
|
|
1047
|
-
for (let i = 1; i < n - 1; i++) {
|
|
1048
|
-
const h0 = x[i] - x[i - 1];
|
|
1049
|
-
const h1 = x[i + 1] - x[i];
|
|
1050
|
-
const a = h0 / 6;
|
|
1051
|
-
const b = (h0 + h1) / 3;
|
|
1052
|
-
const cc = h1 / 6;
|
|
1053
|
-
const r = (y[i + 1] - y[i]) / h1 - (y[i] - y[i - 1]) / h0;
|
|
1054
|
-
const denom = b - a * c[i - 1];
|
|
1055
|
-
c[i] = cc / denom;
|
|
1056
|
-
d[i] = (r - a * d[i - 1]) / denom;
|
|
1057
|
-
}
|
|
1058
|
-
for (let i = n - 2; i >= 1; i--) m2[i] = d[i] - c[i] * m2[i + 1];
|
|
1059
|
-
}
|
|
1060
|
-
let seg = 0;
|
|
1061
|
-
for (let k = 0; k < size; k++) {
|
|
1062
|
-
const xv = k / (size - 1);
|
|
1063
|
-
if (xv <= x[0]) {
|
|
1064
|
-
out[k] = clamp01(y[0]);
|
|
1065
|
-
continue;
|
|
1066
|
-
}
|
|
1067
|
-
if (xv >= x[n - 1]) {
|
|
1068
|
-
out[k] = clamp01(y[n - 1]);
|
|
1069
|
-
continue;
|
|
1070
|
-
}
|
|
1071
|
-
while (seg < n - 2 && xv > x[seg + 1]) seg++;
|
|
1072
|
-
const x0 = x[seg], x1 = x[seg + 1];
|
|
1073
|
-
const h = x1 - x0;
|
|
1074
|
-
const a = (x1 - xv) / h;
|
|
1075
|
-
const b = (xv - x0) / h;
|
|
1076
|
-
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;
|
|
1077
|
-
out[k] = clamp01(v);
|
|
1078
|
-
}
|
|
1079
|
-
return out;
|
|
1080
1037
|
}
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
var INF = 1e20;
|
|
1085
|
-
var FAR = 1e9;
|
|
1086
|
-
var STROKE_CHAMFER_MAX = 20;
|
|
1087
|
-
var BEVEL_H_EPS = 1e-5;
|
|
1088
|
-
var fmap = (w, h, fill2 = 0) => {
|
|
1089
|
-
const v = new Float32Array(w * h);
|
|
1090
|
-
if (fill2) v.fill(fill2);
|
|
1091
|
-
return { w, h, v };
|
|
1092
|
-
};
|
|
1093
|
-
var clamp = (v, lo, hi) => v < lo ? lo : v > hi ? hi : v;
|
|
1094
|
-
var clamp012 = (v) => v <= 0 ? 0 : v >= 1 ? 1 : v;
|
|
1095
|
-
function mapGet(m, x, y) {
|
|
1096
|
-
return x < 0 || y < 0 || x >= m.w || y >= m.h ? 0 : m.v[y * m.w + x];
|
|
1038
|
+
function lightOffset(angle, distance) {
|
|
1039
|
+
const a = angle * Math.PI / 180;
|
|
1040
|
+
return [Math.round(-Math.cos(a) * distance), Math.round(Math.sin(a) * distance)];
|
|
1097
1041
|
}
|
|
1098
|
-
function
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
const
|
|
1103
|
-
const
|
|
1104
|
-
const
|
|
1105
|
-
|
|
1106
|
-
const
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1042
|
+
function spreadSplit(size, spread) {
|
|
1043
|
+
return [Math.round(size * spread), size * (1 - spread)];
|
|
1044
|
+
}
|
|
1045
|
+
function shadowMap(shape, s, spread, light, inner, ox, oy) {
|
|
1046
|
+
const angle = s.useGlobalLight ? light.angle : s.angle;
|
|
1047
|
+
const [dx, dy] = lightOffset(angle, s.distance);
|
|
1048
|
+
const src = inner ? mapped(shape, (a) => 1 - a) : shape;
|
|
1049
|
+
let m = shifted(src, dx, dy, inner ? 1 : 0);
|
|
1050
|
+
const [r, bw] = spreadSplit(s.size, spread);
|
|
1051
|
+
m = dilate(m, r);
|
|
1052
|
+
blur(m, bw);
|
|
1053
|
+
m = applyLut(m, contourLut(s.contour));
|
|
1054
|
+
noise(m, s.noise, ox, oy);
|
|
1055
|
+
if (inner) for (let i = 0; i < m.v.length; i++) m.v[i] *= shape.v[i];
|
|
1056
|
+
return m;
|
|
1057
|
+
}
|
|
1058
|
+
function glowMap(shape, g, ox, oy) {
|
|
1059
|
+
const inner = g.kind === "inner-glow";
|
|
1060
|
+
const spread = inner ? g.choke : g.spread;
|
|
1061
|
+
const src = inner ? mapped(shape, (a) => 1 - a) : shape;
|
|
1062
|
+
let m;
|
|
1063
|
+
if (g.technique === "precise") {
|
|
1064
|
+
const d = inner ? distInside(shape, false) : distOutside(src, false);
|
|
1065
|
+
const solid = g.size * spread;
|
|
1066
|
+
const soft = Math.max(g.size + 1 - solid, 1e-3);
|
|
1067
|
+
m = fmap(shape.w, shape.h);
|
|
1068
|
+
for (let i = 0; i < d.length; i++) {
|
|
1069
|
+
const di = d[i] + 0.5;
|
|
1070
|
+
m.v[i] = di <= solid ? 1 : 0.5 * clamp012(1 - (di - solid) / soft);
|
|
1116
1071
|
}
|
|
1072
|
+
} else {
|
|
1073
|
+
const [r, bw] = spreadSplit(g.size, spread);
|
|
1074
|
+
m = dilate(src, r);
|
|
1075
|
+
if (m === src || m === shape) m = { w: m.w, h: m.h, v: new Float32Array(m.v) };
|
|
1076
|
+
blur(m, bw);
|
|
1117
1077
|
}
|
|
1118
|
-
|
|
1078
|
+
m = applyLut(m, rangedLut(g.contour, g.range));
|
|
1079
|
+
if (inner && g.source === "center") m = mapped(m, (v) => 1 - v);
|
|
1080
|
+
noise(m, g.noise, ox, oy);
|
|
1081
|
+
if (inner) for (let i = 0; i < m.v.length; i++) m.v[i] *= shape.v[i];
|
|
1082
|
+
return m;
|
|
1119
1083
|
}
|
|
1120
|
-
function
|
|
1121
|
-
const
|
|
1122
|
-
|
|
1123
|
-
|
|
1084
|
+
function satinMap(shape, s) {
|
|
1085
|
+
const [dx, dy] = lightOffset(s.angle, Math.max(1, s.distance));
|
|
1086
|
+
const a = shifted(shape, dx, dy, 0);
|
|
1087
|
+
const b = shifted(shape, -dx, -dy, 0);
|
|
1088
|
+
tent(a, s.size);
|
|
1089
|
+
tent(b, s.size);
|
|
1090
|
+
let m = fmap(shape.w, shape.h);
|
|
1091
|
+
for (let i = 0; i < m.v.length; i++) m.v[i] = Math.abs(a.v[i] - b.v[i]);
|
|
1092
|
+
if (s.invert) m = mapped(m, (v) => 1 - v);
|
|
1093
|
+
m = applyLut(m, satinLut(s.contour));
|
|
1094
|
+
for (let i = 0; i < m.v.length; i++) m.v[i] *= shape.v[i];
|
|
1095
|
+
return m;
|
|
1124
1096
|
}
|
|
1125
|
-
function
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
v[k] = q;
|
|
1146
|
-
z[k] = s;
|
|
1147
|
-
z[k + 1] = Infinity;
|
|
1148
|
-
break;
|
|
1149
|
-
}
|
|
1097
|
+
function bevelGeom(b) {
|
|
1098
|
+
const size = Math.max(b.size, 1);
|
|
1099
|
+
const emboss = b.style === "emboss" || b.style === "pillow-emboss";
|
|
1100
|
+
const paint2 = b.style === "outer-bevel" ? "outer" : emboss ? "both" : "inner";
|
|
1101
|
+
const width = emboss ? Math.ceil(size / 2) : size;
|
|
1102
|
+
const smooth = b.technique === "smooth";
|
|
1103
|
+
const sign = b.direction === "up" ? 1 : -1;
|
|
1104
|
+
return {
|
|
1105
|
+
paint: paint2,
|
|
1106
|
+
width,
|
|
1107
|
+
depth: b.depth * (smooth ? width : size / 2) * sign,
|
|
1108
|
+
pillow: b.style === "pillow-emboss",
|
|
1109
|
+
chiselSoft: b.technique === "chisel-soft" ? Math.max(size / 4, 1) : 0
|
|
1110
|
+
};
|
|
1111
|
+
}
|
|
1112
|
+
function bevelChiselH(paint2, size, din, dout, soft) {
|
|
1113
|
+
const ramp = size + 1;
|
|
1114
|
+
if (paint2 === "outer" && !soft) {
|
|
1115
|
+
const top = (size + 2) / ramp;
|
|
1116
|
+
return dout > 0 ? clamp((size + 1.5 - dout) / ramp, 0, top) : top;
|
|
1150
1117
|
}
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
const d = q - p;
|
|
1156
|
-
out[q] = d * d + f[p];
|
|
1157
|
-
near[q] = p;
|
|
1118
|
+
if (paint2 === "outer") return dout > 0 ? 1 - clamp012((dout + 0.5) / ramp) : (size + 2) / ramp;
|
|
1119
|
+
if (paint2 === "both") {
|
|
1120
|
+
const half = size / 2 + 0.5;
|
|
1121
|
+
return din > 0 ? 0.5 + 0.5 * clamp012(din / half) : 0.5 - 0.5 * clamp012(dout / half);
|
|
1158
1122
|
}
|
|
1123
|
+
if (soft) return din > 0 ? clamp((din + 1.5) / ramp, 0, (size + 2) / ramp) : 0;
|
|
1124
|
+
return din > 0 ? clamp012((din + 0.5) / ramp) : 0;
|
|
1159
1125
|
}
|
|
1160
|
-
function
|
|
1161
|
-
const
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
dt1(f, h, o, nr, v, z);
|
|
1173
|
-
for (let y = 0; y < h; y++) {
|
|
1174
|
-
gc[x * h + y] = o[y];
|
|
1175
|
-
nc[x * h + y] = nr[y];
|
|
1176
|
-
}
|
|
1126
|
+
function bevelHeight(shape, b, g, rect, anchor, ctx) {
|
|
1127
|
+
const size = Math.max(b.size, 1);
|
|
1128
|
+
let h;
|
|
1129
|
+
if (b.technique === "smooth") {
|
|
1130
|
+
h = { w: shape.w, h: shape.h, v: new Float32Array(shape.v) };
|
|
1131
|
+
tent(h, g.width);
|
|
1132
|
+
} else {
|
|
1133
|
+
const { din, dout } = edgeDistances(shape, size + 2);
|
|
1134
|
+
h = fmap(shape.w, shape.h);
|
|
1135
|
+
const soft = g.chiselSoft > 0;
|
|
1136
|
+
for (let i = 0; i < h.v.length; i++) h.v[i] = bevelChiselH(g.paint, size, din[i], dout[i], soft);
|
|
1137
|
+
if (soft && g.paint === "both") tent(h, g.chiselSoft);
|
|
1177
1138
|
}
|
|
1178
|
-
|
|
1179
|
-
const
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1139
|
+
if (b.contourElement) h = applyLut(h, _nullishCoalesce(contourLut(b.contourElement.contour), () => ( identityLut())));
|
|
1140
|
+
const t = b.texture;
|
|
1141
|
+
const tile = t ? ctx.pattern(t.patternId) : null;
|
|
1142
|
+
if (t && tile) {
|
|
1143
|
+
const unit = Math.abs(b.depth) > 1e-6 ? Math.max(Math.abs(g.depth / b.depth), 1e-3) : Math.max(g.width, 1);
|
|
1144
|
+
const place = new PatternPlacement(anchor, _nullishCoalesce(t.link, () => ( true)), _nullishCoalesce(t.phase, () => ( { x: 0, y: 0 })), t.scale, 0);
|
|
1145
|
+
const k = t.depth / unit;
|
|
1146
|
+
const uv = [0, 0];
|
|
1147
|
+
const p = [0, 0, 0, 0];
|
|
1148
|
+
for (let y = 0; y < h.h; y++) {
|
|
1149
|
+
for (let x = 0; x < h.w; x++) {
|
|
1150
|
+
place.map(rect.x + x + 0.5, rect.y + y + 0.5, uv);
|
|
1151
|
+
tile.sample(uv[0], uv[1], p);
|
|
1152
|
+
const l = (0.299 * p[0] + 0.587 * p[1] + 0.114 * p[2]) * p[3];
|
|
1153
|
+
h.v[y * h.w + x] += k * (t.invert ? 1 - l : l);
|
|
1154
|
+
}
|
|
1187
1155
|
}
|
|
1188
1156
|
}
|
|
1189
|
-
|
|
1157
|
+
if (b.soften >= 1) tent(h, b.soften);
|
|
1158
|
+
return h;
|
|
1190
1159
|
}
|
|
1191
|
-
var
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
const
|
|
1205
|
-
const
|
|
1206
|
-
const
|
|
1207
|
-
const
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1160
|
+
var identity = null;
|
|
1161
|
+
function identityLut() {
|
|
1162
|
+
if (!identity) {
|
|
1163
|
+
identity = new Float32Array(4096);
|
|
1164
|
+
for (let k = 0; k < 4096; k++) identity[k] = k / 4095;
|
|
1165
|
+
}
|
|
1166
|
+
return identity;
|
|
1167
|
+
}
|
|
1168
|
+
function bevelMaps(shape, b, rect, anchor, ctx) {
|
|
1169
|
+
const g = bevelGeom(b);
|
|
1170
|
+
const hmap = bevelHeight(shape, b, g, rect, anchor, ctx);
|
|
1171
|
+
const angle = b.useGlobalLight ? ctx.light.angle : b.angle;
|
|
1172
|
+
const altitude = b.useGlobalLight ? ctx.light.altitude : b.altitude;
|
|
1173
|
+
const sa = Math.sin(angle * Math.PI / 180);
|
|
1174
|
+
const ca = Math.cos(angle * Math.PI / 180);
|
|
1175
|
+
const se = Math.sin(altitude * Math.PI / 180);
|
|
1176
|
+
const ce = Math.cos(altitude * Math.PI / 180);
|
|
1177
|
+
const lx = ca * ce;
|
|
1178
|
+
const ly = -sa * ce;
|
|
1179
|
+
const lz = se;
|
|
1180
|
+
const reachPast = g.paint === "both" || g.paint === "outer" && b.technique !== "smooth";
|
|
1181
|
+
const onBevel = (x, y) => mapGet(hmap, x, y) > BEVEL_H_EPS || reachPast && (mapGet(hmap, x + 1, y) > BEVEL_H_EPS || mapGet(hmap, x - 1, y) > BEVEL_H_EPS || mapGet(hmap, x, y + 1) > BEVEL_H_EPS || mapGet(hmap, x, y - 1) > BEVEL_H_EPS);
|
|
1182
|
+
const gloss = contourLut(b.glossContour);
|
|
1183
|
+
const shadeInto = (depth, outside) => {
|
|
1184
|
+
const hi2 = fmap(shape.w, shape.h);
|
|
1185
|
+
const sh2 = fmap(shape.w, shape.h);
|
|
1186
|
+
for (let y = 0; y < shape.h; y++) {
|
|
1187
|
+
for (let x = 0; x < shape.w; x++) {
|
|
1188
|
+
const i = y * shape.w + x;
|
|
1189
|
+
const gx = (mapGet(hmap, x + 1, y) - mapGet(hmap, x - 1, y)) * 0.5 * depth;
|
|
1190
|
+
const gy = (mapGet(hmap, x, y + 1) - mapGet(hmap, x, y - 1)) * 0.5 * depth;
|
|
1191
|
+
const len = Math.sqrt(gx * gx + gy * gy + 1);
|
|
1192
|
+
const shade = (-gx * lx - gy * ly + lz) / len;
|
|
1193
|
+
const region = outside ? shape.v[i] < 1 - INSIDE_EPS && onBevel(x, y) ? 1 : 0 : shape.v[i];
|
|
1194
|
+
const k = shade - se;
|
|
1195
|
+
if (k > 0) hi2.v[i] = clamp012(k / Math.max(1 - se, 1e-3)) * region;
|
|
1196
|
+
else sh2.v[i] = clamp012(-k / Math.max(se, 1e-3)) * region;
|
|
1224
1197
|
}
|
|
1225
1198
|
}
|
|
1199
|
+
return [applyLut(hi2, gloss), applyLut(sh2, gloss)];
|
|
1200
|
+
};
|
|
1201
|
+
if (g.paint !== "both") {
|
|
1202
|
+
const [hi2, sh2] = shadeInto(g.depth, g.paint === "outer");
|
|
1203
|
+
return { maps: [hi2, sh2], paint: g.paint };
|
|
1226
1204
|
}
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
for (let i = 0; i < n; i++) start[i] = v[i] > INSIDE_EPS ? 1 - Math.min(v[i], 1) : INF;
|
|
1236
|
-
const d2 = chamferFrom(start, w, h);
|
|
1237
|
-
for (let i = 0; i < n; i++) out[i] = v[i] > INSIDE_EPS ? -0.5 : d2[i] - 0.5;
|
|
1205
|
+
const [hi, sh] = shadeInto(g.depth, false);
|
|
1206
|
+
const [ho, so] = shadeInto(g.pillow ? -g.depth : g.depth, true);
|
|
1207
|
+
const mix = (a, o) => {
|
|
1208
|
+
const out = fmap(a.w, a.h);
|
|
1209
|
+
for (let i = 0; i < out.v.length; i++) {
|
|
1210
|
+
const s = shape.v[i];
|
|
1211
|
+
out.v[i] = (s > INSIDE_EPS ? a.v[i] : 0) + o.v[i] * (1 - Math.min(s, 1));
|
|
1212
|
+
}
|
|
1238
1213
|
return out;
|
|
1239
|
-
}
|
|
1240
|
-
|
|
1241
|
-
for (let i = 0; i < n; i++) inside[i] = v[i] > INSIDE_EPS ? 1 : 0;
|
|
1242
|
-
const { d, near } = edtNearest(inside, w, h);
|
|
1243
|
-
for (let i = 0; i < n; i++) out[i] = inside[i] ? -0.5 : d[i] - 0.5 + (1 - Math.min(v[near[i]], 1));
|
|
1244
|
-
return out;
|
|
1214
|
+
};
|
|
1215
|
+
return { maps: [mix(hi, ho), mix(sh, so)], paint: "both" };
|
|
1245
1216
|
}
|
|
1246
|
-
function
|
|
1247
|
-
|
|
1248
|
-
for (let y = 0; y < s.h; y++) {
|
|
1249
|
-
for (let x = 0; x < s.w; x++) {
|
|
1250
|
-
const a = s.v[y * s.w + x];
|
|
1251
|
-
if (a <= INSIDE_EPS) continue;
|
|
1252
|
-
let mx = a;
|
|
1253
|
-
for (let dy = -1; dy <= 1; dy++) for (let dx = -1; dx <= 1; dx++) mx = Math.max(mx, mapGet(s, x + dx, y + dy));
|
|
1254
|
-
out.v[y * s.w + x] = Math.min(a / mx, 1);
|
|
1255
|
-
}
|
|
1256
|
-
}
|
|
1257
|
-
return out;
|
|
1217
|
+
function strokeWidths(s) {
|
|
1218
|
+
return s.position === "outside" ? [0, s.size] : s.position === "inside" ? [s.size, 0] : [s.size / 2, s.size / 2];
|
|
1258
1219
|
}
|
|
1259
|
-
function
|
|
1260
|
-
|
|
1261
|
-
const
|
|
1262
|
-
|
|
1263
|
-
if (chamfer) {
|
|
1264
|
-
const cov = localCoverage(s);
|
|
1265
|
-
const start = new Float32Array(n);
|
|
1266
|
-
for (let i = 0; i < n; i++) start[i] = v[i] <= INSIDE_EPS ? 0 : cov.v[i] < 1 - INSIDE_EPS ? cov.v[i] : INF;
|
|
1267
|
-
const d2 = chamferFrom(start, w, h);
|
|
1268
|
-
for (let i = 0; i < n; i++) out[i] = v[i] <= INSIDE_EPS ? -0.5 : d2[i] - 0.5;
|
|
1269
|
-
return out;
|
|
1270
|
-
}
|
|
1271
|
-
const outside = new Uint8Array(n);
|
|
1272
|
-
for (let i = 0; i < n; i++) outside[i] = v[i] <= INSIDE_EPS ? 1 : 0;
|
|
1273
|
-
const { d } = edtNearest(outside, w, h);
|
|
1274
|
-
for (let i = 0; i < n; i++) out[i] = outside[i] ? -0.5 : d[i] - 0.5;
|
|
1275
|
-
return out;
|
|
1220
|
+
function activeEffectItems(effects) {
|
|
1221
|
+
if (!hasActiveEffects(effects)) return [];
|
|
1222
|
+
const s = effectsScale(effects);
|
|
1223
|
+
return effects.items.filter((e) => e.enabled).map((e) => scaleLayerEffect(e, s));
|
|
1276
1224
|
}
|
|
1277
|
-
function
|
|
1278
|
-
const
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1225
|
+
function effectsAreLocal(items) {
|
|
1226
|
+
const linked = (p) => p.link !== false;
|
|
1227
|
+
return items.every((e) => {
|
|
1228
|
+
switch (e.kind) {
|
|
1229
|
+
case "gradient-overlay":
|
|
1230
|
+
return !e.gradient.align;
|
|
1231
|
+
case "pattern-overlay":
|
|
1232
|
+
return !linked(e);
|
|
1233
|
+
case "stroke":
|
|
1234
|
+
return e.fill.type === "color" || e.fill.type === "pattern" && !linked(e.fill);
|
|
1235
|
+
case "drop-shadow":
|
|
1236
|
+
case "inner-shadow":
|
|
1237
|
+
case "outer-glow":
|
|
1238
|
+
case "inner-glow":
|
|
1239
|
+
return e.noise <= 0;
|
|
1240
|
+
case "bevel-emboss":
|
|
1241
|
+
return !e.texture || !linked(e.texture);
|
|
1242
|
+
default:
|
|
1243
|
+
return true;
|
|
1289
1244
|
}
|
|
1290
|
-
}
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
const
|
|
1294
|
-
|
|
1295
|
-
for (let x = 0; x < w; x++)
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
}
|
|
1318
|
-
sd = (x - qx) * nx + (y - qy) * ny - (Math.min(v[q], 1) - 0.5);
|
|
1245
|
+
});
|
|
1246
|
+
}
|
|
1247
|
+
function shapeBounds(shape, rect) {
|
|
1248
|
+
const { width: w, height: h } = rect;
|
|
1249
|
+
const rowHit = (y) => {
|
|
1250
|
+
for (let x = 0, i = y * w; x < w; x++, i++) if (shape[i] > INSIDE_EPS) return true;
|
|
1251
|
+
return false;
|
|
1252
|
+
};
|
|
1253
|
+
let y0 = 0;
|
|
1254
|
+
while (y0 < h && !rowHit(y0)) y0++;
|
|
1255
|
+
if (y0 === h) return null;
|
|
1256
|
+
let y1 = h - 1;
|
|
1257
|
+
while (!rowHit(y1)) y1--;
|
|
1258
|
+
let x0 = w;
|
|
1259
|
+
let x1 = -1;
|
|
1260
|
+
for (let y = y0; y <= y1; y++) {
|
|
1261
|
+
const o = y * w;
|
|
1262
|
+
for (let x = 0; x < x0; x++) {
|
|
1263
|
+
if (shape[o + x] > INSIDE_EPS) {
|
|
1264
|
+
x0 = x;
|
|
1265
|
+
break;
|
|
1266
|
+
}
|
|
1267
|
+
}
|
|
1268
|
+
for (let x = w - 1; x > x1; x--) {
|
|
1269
|
+
if (shape[o + x] > INSIDE_EPS) {
|
|
1270
|
+
x1 = x;
|
|
1271
|
+
break;
|
|
1319
1272
|
}
|
|
1320
|
-
din[i] = inside[i] ? Math.max(-sd, inside[i] && !edge[i] ? 0.5 : -0.5) : -0.5;
|
|
1321
|
-
dout[i] = inside[i] && !edge[i] ? -0.5 : Math.max(sd, -0.5);
|
|
1322
1273
|
}
|
|
1323
1274
|
}
|
|
1324
|
-
return {
|
|
1325
|
-
}
|
|
1326
|
-
function dilate(s, r) {
|
|
1327
|
-
if (!(r > 0)) return s;
|
|
1328
|
-
const d = distOutside(s, true);
|
|
1329
|
-
const out = { w: s.w, h: s.h, v: new Float32Array(s.v) };
|
|
1330
|
-
for (let i = 0; i < d.length; i++) {
|
|
1331
|
-
const o = out.v[i];
|
|
1332
|
-
out.v[i] = d[i] < 0 ? Math.min(o + r, 1) : Math.max(o, clamp012(r + 0.5 - d[i]));
|
|
1333
|
-
}
|
|
1334
|
-
return out;
|
|
1335
|
-
}
|
|
1336
|
-
function boxWidth(w) {
|
|
1337
|
-
return Number.isNaN(w) ? 1 : clamp(w, 1, MAX_EFFECT_REACH);
|
|
1338
|
-
}
|
|
1339
|
-
function boxGeom(bw) {
|
|
1340
|
-
bw = boxWidth(bw);
|
|
1341
|
-
const half = bw / 2;
|
|
1342
|
-
const r = Math.max(0, Math.ceil(half - 0.5));
|
|
1343
|
-
const f = clamp012(half - (r - 0.5));
|
|
1344
|
-
return [r, f, 1 / bw];
|
|
1345
|
-
}
|
|
1346
|
-
function boxLine(src, x0, dst, bw) {
|
|
1347
|
-
const n = src.length;
|
|
1348
|
-
const [r, f, norm] = boxGeom(bw);
|
|
1349
|
-
const at = (i) => i >= 0 && i < n ? src[i] : 0;
|
|
1350
|
-
if (r === 0) {
|
|
1351
|
-
for (let k = 0; k < dst.length; k++) dst[k] = at(x0 + k);
|
|
1352
|
-
return;
|
|
1353
|
-
}
|
|
1354
|
-
let inner = 0;
|
|
1355
|
-
for (let i = x0 - (r - 1); i <= x0 + (r - 1); i++) inner += at(i);
|
|
1356
|
-
for (let k = 0; k < dst.length; k++) {
|
|
1357
|
-
const x = x0 + k;
|
|
1358
|
-
dst[k] = (inner + f * (at(x - r) + at(x + r))) * norm;
|
|
1359
|
-
inner += at(x + r) - at(x - r + 1);
|
|
1360
|
-
}
|
|
1361
|
-
}
|
|
1362
|
-
var BLUR_EPS = 1e-7;
|
|
1363
|
-
var BLUR_FIX = 2 ** 32;
|
|
1364
|
-
function tentLine(src, dst, bw, mid) {
|
|
1365
|
-
const [r] = boxGeom(bw);
|
|
1366
|
-
const m = mid.subarray(0, src.length + 2 * r);
|
|
1367
|
-
for (let i = 0; i < src.length; i++) src[i] = Math.round(src[i] * BLUR_FIX);
|
|
1368
|
-
boxLine(src, -r, m, bw);
|
|
1369
|
-
for (let i = 0; i < m.length; i++) m[i] = Math.round(m[i]);
|
|
1370
|
-
boxLine(m, r, dst, bw);
|
|
1371
|
-
for (let i = 0; i < dst.length; i++) {
|
|
1372
|
-
const v = dst[i] / BLUR_FIX;
|
|
1373
|
-
dst[i] = Math.abs(v) < BLUR_EPS ? 0 : v;
|
|
1374
|
-
}
|
|
1275
|
+
return { x: rect.x + x0, y: rect.y + y0, width: x1 - x0 + 1, height: y1 - y0 + 1 };
|
|
1375
1276
|
}
|
|
1376
|
-
function
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
const { w
|
|
1380
|
-
const
|
|
1381
|
-
const
|
|
1382
|
-
const
|
|
1383
|
-
const
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
if (pts.length >= 2 && !linear) {
|
|
1409
|
-
if (!pts.some((p) => p.corner)) lut = curveLut(pts);
|
|
1410
|
-
else {
|
|
1411
|
-
const sorted = [...pts].sort((a, b) => a.input - b.input);
|
|
1412
|
-
let start = 0;
|
|
1413
|
-
for (let i = 1; i < sorted.length; i++) {
|
|
1414
|
-
if (!(sorted[i].corner || i === sorted.length - 1)) continue;
|
|
1415
|
-
const seg = sorted.slice(start, i + 1);
|
|
1416
|
-
const from = seg[0].input;
|
|
1417
|
-
const part = curveLut(seg);
|
|
1418
|
-
if (!lut) lut = part;
|
|
1419
|
-
else for (let k = 0; k < part.length; k++) if (k / (part.length - 1) >= from) lut[k] = part[k];
|
|
1420
|
-
start = i;
|
|
1277
|
+
function buildEffectMaps(items, shape, rect, ctx) {
|
|
1278
|
+
const w = rect.width;
|
|
1279
|
+
const h = rect.height;
|
|
1280
|
+
const s = { w, h, v: shape };
|
|
1281
|
+
const bounds = shapeBounds(shape, rect);
|
|
1282
|
+
const anchor = bounds ? { x: bounds.x, y: bounds.y } : { x: rect.x, y: rect.y };
|
|
1283
|
+
const per = [];
|
|
1284
|
+
const bevelPaint = [];
|
|
1285
|
+
const frames = /* @__PURE__ */ new Map();
|
|
1286
|
+
let bytes = shape.byteLength;
|
|
1287
|
+
items.forEach((e, i) => {
|
|
1288
|
+
let maps = [];
|
|
1289
|
+
let paint2 = null;
|
|
1290
|
+
switch (e.kind) {
|
|
1291
|
+
case "drop-shadow":
|
|
1292
|
+
maps = [shadowMap(s, e, e.spread, ctx.light, false, rect.x, rect.y)];
|
|
1293
|
+
break;
|
|
1294
|
+
case "inner-shadow":
|
|
1295
|
+
maps = [shadowMap(s, e, e.choke, ctx.light, true, rect.x, rect.y)];
|
|
1296
|
+
break;
|
|
1297
|
+
case "outer-glow":
|
|
1298
|
+
case "inner-glow":
|
|
1299
|
+
maps = [glowMap(s, e, rect.x, rect.y)];
|
|
1300
|
+
break;
|
|
1301
|
+
case "satin":
|
|
1302
|
+
maps = [satinMap(s, e)];
|
|
1303
|
+
break;
|
|
1304
|
+
case "bevel-emboss": {
|
|
1305
|
+
const r = bevelMaps(s, e, rect, anchor, ctx);
|
|
1306
|
+
maps = r.maps;
|
|
1307
|
+
paint2 = r.paint;
|
|
1308
|
+
break;
|
|
1421
1309
|
}
|
|
1422
|
-
|
|
1310
|
+
case "stroke":
|
|
1311
|
+
if (e.fill.type === "gradient" && bounds) {
|
|
1312
|
+
const grow = Math.max(0, Math.ceil(Math.min(strokeWidths(e)[1], MAX_EFFECT_REACH)) - 1);
|
|
1313
|
+
frames.set(i, { x: bounds.x - grow, y: bounds.y - grow, width: bounds.width + 2 * grow, height: bounds.height + 2 * grow });
|
|
1314
|
+
}
|
|
1315
|
+
break;
|
|
1423
1316
|
}
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
}
|
|
1428
|
-
|
|
1429
|
-
const
|
|
1430
|
-
const
|
|
1431
|
-
const
|
|
1432
|
-
|
|
1317
|
+
per.push(maps.map((m) => m.v));
|
|
1318
|
+
bevelPaint.push(paint2);
|
|
1319
|
+
for (const m of maps) bytes += m.v.byteLength;
|
|
1320
|
+
});
|
|
1321
|
+
const strokes = items.filter((e) => e.kind === "stroke");
|
|
1322
|
+
const outW = strokes.map((st) => strokeWidths(st)[1]).filter((x) => x > 0);
|
|
1323
|
+
const din = strokes.length ? distInside(s, true) : null;
|
|
1324
|
+
const dout = outW.some((x) => x < STROKE_CHAMFER_MAX) ? distOutside(s, true) : null;
|
|
1325
|
+
const doutExact = outW.some((x) => x >= STROKE_CHAMFER_MAX) ? distOutside(s, false) : null;
|
|
1326
|
+
for (const d of [din, dout, doutExact]) if (d) bytes += d.byteLength;
|
|
1327
|
+
return { rect, items, bounds, shape, per, bevelPaint, din, dout, doutExact, frames, bytes };
|
|
1433
1328
|
}
|
|
1434
|
-
|
|
1435
|
-
|
|
1329
|
+
var rectArea = (r) => r.width * r.height;
|
|
1330
|
+
function clipRect(a, b) {
|
|
1331
|
+
const x0 = Math.max(a.x, b.x);
|
|
1332
|
+
const y0 = Math.max(a.y, b.y);
|
|
1333
|
+
const x1 = Math.min(a.x + a.width, b.x + b.width);
|
|
1334
|
+
const y1 = Math.min(a.y + a.height, b.y + b.height);
|
|
1335
|
+
return x1 > x0 && y1 > y0 ? { x: x0, y: y0, width: x1 - x0, height: y1 - y0 } : null;
|
|
1436
1336
|
}
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
const
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
const out = new Float32Array(n);
|
|
1443
|
-
for (let k = 0; k < n; k++) {
|
|
1444
|
-
const v = Math.min(k / (n - 1) / r, 1);
|
|
1445
|
-
out[k] = base ? lutAt(base, v) : v;
|
|
1446
|
-
}
|
|
1447
|
-
return out;
|
|
1337
|
+
var growRect = (r, m) => ({ x: r.x - m, y: r.y - m, width: r.width + 2 * m, height: r.height + 2 * m });
|
|
1338
|
+
function unionRect(a, b) {
|
|
1339
|
+
const x0 = Math.min(a.x, b.x);
|
|
1340
|
+
const y0 = Math.min(a.y, b.y);
|
|
1341
|
+
return { x: x0, y: y0, width: Math.max(a.x + a.width, b.x + b.width) - x0, height: Math.max(a.y + a.height, b.y + b.height) - y0 };
|
|
1448
1342
|
}
|
|
1449
|
-
function
|
|
1450
|
-
const
|
|
1451
|
-
if (!
|
|
1452
|
-
const
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1343
|
+
function rectMinus(r, cut) {
|
|
1344
|
+
const i = clipRect(r, cut);
|
|
1345
|
+
if (!i) return [r];
|
|
1346
|
+
const parts = [
|
|
1347
|
+
{ x: r.x, y: r.y, width: r.width, height: i.y - r.y },
|
|
1348
|
+
{ x: r.x, y: i.y + i.height, width: r.width, height: r.y + r.height - (i.y + i.height) },
|
|
1349
|
+
{ x: r.x, y: i.y, width: i.x - r.x, height: i.height },
|
|
1350
|
+
{ x: i.x + i.width, y: i.y, width: r.x + r.width - (i.x + i.width), height: i.height }
|
|
1351
|
+
];
|
|
1352
|
+
return parts.filter((p) => p.width > 0 && p.height > 0);
|
|
1456
1353
|
}
|
|
1457
|
-
function
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
const i = y * m.w + x;
|
|
1462
|
-
if (m.v[i] <= BLUR_EPS) continue;
|
|
1463
|
-
m.v[i] = clamp012(m.v[i] + (hashNoise(x0 + x, y0 + y) - 0.5) * 2 * amount);
|
|
1464
|
-
}
|
|
1354
|
+
function pasteMap(dst, to, src, from, a) {
|
|
1355
|
+
for (let y = a.y; y < a.y + a.height; y++) {
|
|
1356
|
+
const s = (y - from.y) * from.width + (a.x - from.x);
|
|
1357
|
+
dst.set(src.subarray(s, s + a.width), (y - to.y) * to.width + (a.x - to.x));
|
|
1465
1358
|
}
|
|
1466
1359
|
}
|
|
1467
|
-
function
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
}
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
}
|
|
1487
|
-
function glowMap(shape, g, ox, oy) {
|
|
1488
|
-
const inner = g.kind === "inner-glow";
|
|
1489
|
-
const spread = inner ? g.choke : g.spread;
|
|
1490
|
-
const src = inner ? mapped(shape, (a) => 1 - a) : shape;
|
|
1491
|
-
let m;
|
|
1492
|
-
if (g.technique === "precise") {
|
|
1493
|
-
const d = inner ? distInside(shape, false) : distOutside(src, false);
|
|
1494
|
-
const solid = g.size * spread;
|
|
1495
|
-
const soft = Math.max(g.size + 1 - solid, 1e-3);
|
|
1496
|
-
m = fmap(shape.w, shape.h);
|
|
1497
|
-
for (let i = 0; i < d.length; i++) {
|
|
1498
|
-
const di = d[i] + 0.5;
|
|
1499
|
-
m.v[i] = di <= solid ? 1 : 0.5 * clamp012(1 - (di - solid) / soft);
|
|
1360
|
+
function patchEffectMaps(prev, items, rect, changed, margin, shapeOver, ctx) {
|
|
1361
|
+
if (!effectsAreLocal(items) || rectArea(rect) <= 0) return null;
|
|
1362
|
+
let areas = [];
|
|
1363
|
+
for (const c of changed) {
|
|
1364
|
+
const a = clipRect(growRect(c, margin), rect);
|
|
1365
|
+
if (a) areas.push(a);
|
|
1366
|
+
}
|
|
1367
|
+
areas.push(...rectMinus(rect, prev.rect));
|
|
1368
|
+
for (let merged = true; merged; ) {
|
|
1369
|
+
merged = false;
|
|
1370
|
+
for (let i = 0; i < areas.length && !merged; i++) {
|
|
1371
|
+
for (let j = i + 1; j < areas.length; j++) {
|
|
1372
|
+
if (clipRect(growRect(areas[i], 2 * margin), areas[j])) {
|
|
1373
|
+
areas[i] = unionRect(areas[i], areas[j]);
|
|
1374
|
+
areas.splice(j, 1);
|
|
1375
|
+
merged = true;
|
|
1376
|
+
break;
|
|
1377
|
+
}
|
|
1378
|
+
}
|
|
1500
1379
|
}
|
|
1501
|
-
} else {
|
|
1502
|
-
const [r, bw] = spreadSplit(g.size, spread);
|
|
1503
|
-
m = dilate(src, r);
|
|
1504
|
-
if (m === src || m === shape) m = { w: m.w, h: m.h, v: new Float32Array(m.v) };
|
|
1505
|
-
blur(m, bw);
|
|
1506
1380
|
}
|
|
1507
|
-
|
|
1508
|
-
if (
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
const
|
|
1515
|
-
const
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1381
|
+
const windows = areas.map((a) => clipRect(growRect(a, margin), rect));
|
|
1382
|
+
if (windows.reduce((n, w) => n + rectArea(w), 0) > rectArea(rect) / 2) return null;
|
|
1383
|
+
const same = rect.x === prev.rect.x && rect.y === prev.rect.y && rect.width === prev.rect.width && rect.height === prev.rect.height;
|
|
1384
|
+
const take = (v) => same ? v : crop(v, prev.rect, rect, 0);
|
|
1385
|
+
const shape = take(prev.shape);
|
|
1386
|
+
const per = prev.per.map((maps) => maps.map(take));
|
|
1387
|
+
const din = prev.din && take(prev.din);
|
|
1388
|
+
const dout = prev.dout && take(prev.dout);
|
|
1389
|
+
const doutExact = prev.doutExact && take(prev.doutExact);
|
|
1390
|
+
areas.forEach((a, k) => {
|
|
1391
|
+
const w = windows[k];
|
|
1392
|
+
const part = buildEffectMaps(items, shapeOver(w), w, ctx);
|
|
1393
|
+
pasteMap(shape, rect, part.shape, w, a);
|
|
1394
|
+
per.forEach((maps, i) => maps.forEach((m, j) => pasteMap(m, rect, part.per[i][j], w, a)));
|
|
1395
|
+
if (din) pasteMap(din, rect, part.din, w, a);
|
|
1396
|
+
if (dout) pasteMap(dout, rect, part.dout, w, a);
|
|
1397
|
+
if (doutExact) pasteMap(doutExact, rect, part.doutExact, w, a);
|
|
1398
|
+
});
|
|
1399
|
+
let bytes = shape.byteLength;
|
|
1400
|
+
for (const maps of per) for (const m of maps) bytes += m.byteLength;
|
|
1401
|
+
for (const d of [din, dout, doutExact]) if (d) bytes += d.byteLength;
|
|
1402
|
+
return { rect, items, bounds: shapeBounds(shape, rect), shape, per, bevelPaint: prev.bevelPaint, din, dout, doutExact, frames: /* @__PURE__ */ new Map(), bytes };
|
|
1525
1403
|
}
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
const
|
|
1532
|
-
const
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
depth: b.depth * (smooth ? width : size / 2) * sign,
|
|
1537
|
-
pillow: b.style === "pillow-emboss",
|
|
1538
|
-
chiselSoft: b.technique === "chisel-soft" ? Math.max(size / 4, 1) : 0
|
|
1539
|
-
};
|
|
1540
|
-
}
|
|
1541
|
-
function bevelChiselH(paint2, size, din, dout, soft) {
|
|
1542
|
-
const ramp = size + 1;
|
|
1543
|
-
if (paint2 === "outer" && !soft) {
|
|
1544
|
-
const top = (size + 2) / ramp;
|
|
1545
|
-
return dout > 0 ? clamp((size + 1.5 - dout) / ramp, 0, top) : top;
|
|
1404
|
+
var rgbScratchB = [0, 0, 0];
|
|
1405
|
+
var rgbScratchS = [0, 0, 0];
|
|
1406
|
+
var rgbScratchM = [0, 0, 0];
|
|
1407
|
+
function compositeAt(dst, i, mode, separable, sr, sg, sb, sa) {
|
|
1408
|
+
if (!(sa > 0)) return;
|
|
1409
|
+
const ab = dst[i + 3];
|
|
1410
|
+
const ao = sa + ab * (1 - sa);
|
|
1411
|
+
if (ao <= 0) {
|
|
1412
|
+
dst[i] = dst[i + 1] = dst[i + 2] = dst[i + 3] = 0;
|
|
1413
|
+
return;
|
|
1546
1414
|
}
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1415
|
+
const b0 = dst[i];
|
|
1416
|
+
const b1 = dst[i + 1];
|
|
1417
|
+
const b2 = dst[i + 2];
|
|
1418
|
+
if (mode === "pigment") {
|
|
1419
|
+
rgbScratchB[0] = b0;
|
|
1420
|
+
rgbScratchB[1] = b1;
|
|
1421
|
+
rgbScratchB[2] = b2;
|
|
1422
|
+
rgbScratchS[0] = sr;
|
|
1423
|
+
rgbScratchS[1] = sg;
|
|
1424
|
+
rgbScratchS[2] = sb;
|
|
1425
|
+
_chunk7ISPWEJAcjs.mixPigmentRgb.call(void 0, rgbScratchB, rgbScratchS, sa / ao, rgbScratchM);
|
|
1426
|
+
dst[i] = rgbScratchM[0];
|
|
1427
|
+
dst[i + 1] = rgbScratchM[1];
|
|
1428
|
+
dst[i + 2] = rgbScratchM[2];
|
|
1429
|
+
dst[i + 3] = ao;
|
|
1430
|
+
return;
|
|
1551
1431
|
}
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1432
|
+
let m0;
|
|
1433
|
+
let m1;
|
|
1434
|
+
let m2;
|
|
1435
|
+
if (mode === "normal") {
|
|
1436
|
+
m0 = sr;
|
|
1437
|
+
m1 = sg;
|
|
1438
|
+
m2 = sb;
|
|
1439
|
+
} else if (separable) {
|
|
1440
|
+
m0 = _chunk7ISPWEJAcjs.blendChannel.call(void 0, mode, b0, sr);
|
|
1441
|
+
m1 = _chunk7ISPWEJAcjs.blendChannel.call(void 0, mode, b1, sg);
|
|
1442
|
+
m2 = _chunk7ISPWEJAcjs.blendChannel.call(void 0, mode, b2, sb);
|
|
1561
1443
|
} else {
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
const unit = Math.abs(b.depth) > 1e-6 ? Math.max(Math.abs(g.depth / b.depth), 1e-3) : Math.max(g.width, 1);
|
|
1573
|
-
const place = new PatternPlacement(anchor, _nullishCoalesce(t.link, () => ( true)), _nullishCoalesce(t.phase, () => ( { x: 0, y: 0 })), t.scale, 0);
|
|
1574
|
-
const k = t.depth / unit;
|
|
1575
|
-
const uv = [0, 0];
|
|
1576
|
-
const p = [0, 0, 0, 0];
|
|
1577
|
-
for (let y = 0; y < h.h; y++) {
|
|
1578
|
-
for (let x = 0; x < h.w; x++) {
|
|
1579
|
-
place.map(rect.x + x + 0.5, rect.y + y + 0.5, uv);
|
|
1580
|
-
tile.sample(uv[0], uv[1], p);
|
|
1581
|
-
const l = (0.299 * p[0] + 0.587 * p[1] + 0.114 * p[2]) * p[3];
|
|
1582
|
-
h.v[y * h.w + x] += k * (t.invert ? 1 - l : l);
|
|
1583
|
-
}
|
|
1584
|
-
}
|
|
1444
|
+
rgbScratchB[0] = b0;
|
|
1445
|
+
rgbScratchB[1] = b1;
|
|
1446
|
+
rgbScratchB[2] = b2;
|
|
1447
|
+
rgbScratchS[0] = sr;
|
|
1448
|
+
rgbScratchS[1] = sg;
|
|
1449
|
+
rgbScratchS[2] = sb;
|
|
1450
|
+
const m = _chunk7ISPWEJAcjs.blendRgb.call(void 0, mode, rgbScratchB, rgbScratchS);
|
|
1451
|
+
m0 = m[0];
|
|
1452
|
+
m1 = m[1];
|
|
1453
|
+
m2 = m[2];
|
|
1585
1454
|
}
|
|
1586
|
-
|
|
1587
|
-
|
|
1455
|
+
const wb = (1 - sa) * ab;
|
|
1456
|
+
const ws = (1 - ab) * sa;
|
|
1457
|
+
const wm = sa * ab;
|
|
1458
|
+
dst[i] = (wb * b0 + ws * sr + wm * m0) / ao;
|
|
1459
|
+
dst[i + 1] = (wb * b1 + ws * sg + wm * m1) / ao;
|
|
1460
|
+
dst[i + 2] = (wb * b2 + ws * sb + wm * m2) / ao;
|
|
1461
|
+
dst[i + 3] = ao;
|
|
1588
1462
|
}
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1463
|
+
function paint(dst, m, color2, mode, opacity) {
|
|
1464
|
+
const sep = mode !== "normal" && _chunk7ISPWEJAcjs.isSeparableBlendMode.call(void 0, mode);
|
|
1465
|
+
const c = [0, 0, 0, 1];
|
|
1466
|
+
const n = m.length;
|
|
1467
|
+
for (let i = 0; i < n; i++) {
|
|
1468
|
+
const a = m[i] * opacity;
|
|
1469
|
+
if (!(a > 0)) continue;
|
|
1470
|
+
color2(i, c);
|
|
1471
|
+
compositeAt(dst, i * 4, mode, sep, c[0], c[1], c[2], c[3] * Math.min(a, 1));
|
|
1594
1472
|
}
|
|
1595
|
-
return identity;
|
|
1596
1473
|
}
|
|
1597
|
-
function
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
const
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1474
|
+
function rgbOf(hex) {
|
|
1475
|
+
return _nullishCoalesce(parseEffectColor(hex), () => ( [0, 0, 0]));
|
|
1476
|
+
}
|
|
1477
|
+
function paintColor(dst, m, hex, mode, opacity) {
|
|
1478
|
+
const [r, g, b] = rgbOf(hex);
|
|
1479
|
+
paint(
|
|
1480
|
+
dst,
|
|
1481
|
+
m,
|
|
1482
|
+
(_i, c) => {
|
|
1483
|
+
c[0] = r;
|
|
1484
|
+
c[1] = g;
|
|
1485
|
+
c[2] = b;
|
|
1486
|
+
c[3] = 1;
|
|
1487
|
+
},
|
|
1488
|
+
mode,
|
|
1489
|
+
opacity
|
|
1490
|
+
);
|
|
1491
|
+
}
|
|
1492
|
+
var PreparedGradient = class {
|
|
1493
|
+
|
|
1494
|
+
|
|
1495
|
+
constructor(g) {
|
|
1496
|
+
this.color = [...g.stops].sort((a, b) => a.position - b.position).map((s) => [s.position, ...rgbOf(s.color)]);
|
|
1497
|
+
this.alpha = [..._nullishCoalesce(g.opacityStops, () => ( []))].sort((a, b) => a.position - b.position).map((s) => [s.position, s.opacity]);
|
|
1498
|
+
}
|
|
1499
|
+
sample(t, out) {
|
|
1500
|
+
const c = this.color;
|
|
1501
|
+
if (!c.length) {
|
|
1502
|
+
out[0] = out[1] = out[2] = t;
|
|
1503
|
+
} else if (c.length === 1 || t <= c[0][0]) {
|
|
1504
|
+
out[0] = c[0][1];
|
|
1505
|
+
out[1] = c[0][2];
|
|
1506
|
+
out[2] = c[0][3];
|
|
1507
|
+
} else {
|
|
1508
|
+
let done = false;
|
|
1509
|
+
for (let k = 0; k < c.length - 1; k++) {
|
|
1510
|
+
const a2 = c[k];
|
|
1511
|
+
const b = c[k + 1];
|
|
1512
|
+
if (t <= b[0]) {
|
|
1513
|
+
const f = b[0] > a2[0] ? (t - a2[0]) / (b[0] - a2[0]) : 0;
|
|
1514
|
+
out[0] = a2[1] + (b[1] - a2[1]) * f;
|
|
1515
|
+
out[1] = a2[2] + (b[2] - a2[2]) * f;
|
|
1516
|
+
out[2] = a2[3] + (b[3] - a2[3]) * f;
|
|
1517
|
+
done = true;
|
|
1518
|
+
break;
|
|
1519
|
+
}
|
|
1520
|
+
}
|
|
1521
|
+
if (!done) {
|
|
1522
|
+
const l = c[c.length - 1];
|
|
1523
|
+
out[0] = l[1];
|
|
1524
|
+
out[1] = l[2];
|
|
1525
|
+
out[2] = l[3];
|
|
1626
1526
|
}
|
|
1627
1527
|
}
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
out.v[i] = (s > INSIDE_EPS ? a.v[i] : 0) + o.v[i] * (1 - Math.min(s, 1));
|
|
1528
|
+
const a = this.alpha;
|
|
1529
|
+
if (!a.length) out[3] = 1;
|
|
1530
|
+
else if (a.length === 1 || t <= a[0][0]) out[3] = a[0][1];
|
|
1531
|
+
else {
|
|
1532
|
+
out[3] = a[a.length - 1][1];
|
|
1533
|
+
for (let k = 0; k < a.length - 1; k++) {
|
|
1534
|
+
if (t <= a[k + 1][0]) {
|
|
1535
|
+
const f = a[k + 1][0] > a[k][0] ? (t - a[k][0]) / (a[k + 1][0] - a[k][0]) : 0;
|
|
1536
|
+
out[3] = a[k][1] + (a[k + 1][1] - a[k][1]) * f;
|
|
1537
|
+
break;
|
|
1538
|
+
}
|
|
1539
|
+
}
|
|
1641
1540
|
}
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
const s = effectsScale(effects);
|
|
1652
|
-
return effects.items.filter((e) => e.enabled).map((e) => scaleLayerEffect(e, s));
|
|
1541
|
+
}
|
|
1542
|
+
};
|
|
1543
|
+
function gradientUnits(angle, w, h) {
|
|
1544
|
+
const a = angle * Math.PI / 180;
|
|
1545
|
+
const s = Math.sin(a);
|
|
1546
|
+
const c = Math.cos(a);
|
|
1547
|
+
const len = Math.max(Math.sqrt((c * w) ** 2 + (s * h) ** 2), 1);
|
|
1548
|
+
const chord = Math.max(Math.min(w / Math.max(Math.abs(c), 1e-6), h / Math.max(Math.abs(s), 1e-6)), 1);
|
|
1549
|
+
return [chord, len];
|
|
1653
1550
|
}
|
|
1654
|
-
function
|
|
1655
|
-
const
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
let x1 = -1;
|
|
1689
|
-
for (let y = y0; y <= y1; y++) {
|
|
1690
|
-
const o = y * w;
|
|
1691
|
-
for (let x = 0; x < x0; x++) {
|
|
1692
|
-
if (shape[o + x] > INSIDE_EPS) {
|
|
1693
|
-
x0 = x;
|
|
1694
|
-
break;
|
|
1695
|
-
}
|
|
1696
|
-
}
|
|
1697
|
-
for (let x = w - 1; x > x1; x--) {
|
|
1698
|
-
if (shape[o + x] > INSIDE_EPS) {
|
|
1699
|
-
x1 = x;
|
|
1700
|
-
break;
|
|
1701
|
-
}
|
|
1551
|
+
function gradientT(style, angle, scale, reverse, offset, frame, x, y) {
|
|
1552
|
+
const w = Math.max(frame.width, 1);
|
|
1553
|
+
const h = Math.max(frame.height, 1);
|
|
1554
|
+
const cx = frame.x + w / 2 + offset.x * w;
|
|
1555
|
+
const cy = frame.y + h / 2 + offset.y * h;
|
|
1556
|
+
const a = angle * Math.PI / 180;
|
|
1557
|
+
const s = Math.sin(a);
|
|
1558
|
+
const c = Math.cos(a);
|
|
1559
|
+
const dx = x - cx;
|
|
1560
|
+
const dy = y - cy;
|
|
1561
|
+
const along = dx * c - dy * s;
|
|
1562
|
+
const across = dx * s + dy * c;
|
|
1563
|
+
let [chord, len] = gradientUnits(angle, w, h);
|
|
1564
|
+
chord *= Math.max(scale, 1e-3);
|
|
1565
|
+
len *= Math.max(scale, 1e-3);
|
|
1566
|
+
const corner = 0.5 * (c - s);
|
|
1567
|
+
let t;
|
|
1568
|
+
switch (style) {
|
|
1569
|
+
case "linear":
|
|
1570
|
+
t = (along - corner) / chord + 0.5;
|
|
1571
|
+
break;
|
|
1572
|
+
case "reflected":
|
|
1573
|
+
t = Math.abs((along - corner) / (chord / 2));
|
|
1574
|
+
break;
|
|
1575
|
+
case "radial":
|
|
1576
|
+
t = Math.sqrt(dx * dx + dy * dy) / (len / 2);
|
|
1577
|
+
break;
|
|
1578
|
+
case "diamond":
|
|
1579
|
+
t = (Math.abs(along) + Math.abs(across)) / (len / 2);
|
|
1580
|
+
break;
|
|
1581
|
+
case "angle": {
|
|
1582
|
+
const turn = (a - Math.atan2(-dy, dx)) / (2 * Math.PI);
|
|
1583
|
+
t = turn - Math.floor(turn);
|
|
1584
|
+
break;
|
|
1702
1585
|
}
|
|
1703
1586
|
}
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
function buildEffectMaps(items, shape, rect, ctx) {
|
|
1707
|
-
const w = rect.width;
|
|
1708
|
-
const h = rect.height;
|
|
1709
|
-
const s = { w, h, v: shape };
|
|
1710
|
-
const bounds = shapeBounds(shape, rect);
|
|
1711
|
-
const anchor = bounds ? { x: bounds.x, y: bounds.y } : { x: rect.x, y: rect.y };
|
|
1712
|
-
const per = [];
|
|
1713
|
-
const bevelPaint = [];
|
|
1714
|
-
const frames = /* @__PURE__ */ new Map();
|
|
1715
|
-
let bytes = shape.byteLength;
|
|
1716
|
-
items.forEach((e, i) => {
|
|
1717
|
-
let maps = [];
|
|
1718
|
-
let paint2 = null;
|
|
1719
|
-
switch (e.kind) {
|
|
1720
|
-
case "drop-shadow":
|
|
1721
|
-
maps = [shadowMap(s, e, e.spread, ctx.light, false, rect.x, rect.y)];
|
|
1722
|
-
break;
|
|
1723
|
-
case "inner-shadow":
|
|
1724
|
-
maps = [shadowMap(s, e, e.choke, ctx.light, true, rect.x, rect.y)];
|
|
1725
|
-
break;
|
|
1726
|
-
case "outer-glow":
|
|
1727
|
-
case "inner-glow":
|
|
1728
|
-
maps = [glowMap(s, e, rect.x, rect.y)];
|
|
1729
|
-
break;
|
|
1730
|
-
case "satin":
|
|
1731
|
-
maps = [satinMap(s, e)];
|
|
1732
|
-
break;
|
|
1733
|
-
case "bevel-emboss": {
|
|
1734
|
-
const r = bevelMaps(s, e, rect, anchor, ctx);
|
|
1735
|
-
maps = r.maps;
|
|
1736
|
-
paint2 = r.paint;
|
|
1737
|
-
break;
|
|
1738
|
-
}
|
|
1739
|
-
case "stroke":
|
|
1740
|
-
if (e.fill.type === "gradient" && bounds) {
|
|
1741
|
-
const grow = Math.max(0, Math.ceil(Math.min(strokeWidths(e)[1], MAX_EFFECT_REACH)) - 1);
|
|
1742
|
-
frames.set(i, { x: bounds.x - grow, y: bounds.y - grow, width: bounds.width + 2 * grow, height: bounds.height + 2 * grow });
|
|
1743
|
-
}
|
|
1744
|
-
break;
|
|
1745
|
-
}
|
|
1746
|
-
per.push(maps.map((m) => m.v));
|
|
1747
|
-
bevelPaint.push(paint2);
|
|
1748
|
-
for (const m of maps) bytes += m.v.byteLength;
|
|
1749
|
-
});
|
|
1750
|
-
const strokes = items.filter((e) => e.kind === "stroke");
|
|
1751
|
-
const outW = strokes.map((st) => strokeWidths(st)[1]).filter((x) => x > 0);
|
|
1752
|
-
const din = strokes.length ? distInside(s, true) : null;
|
|
1753
|
-
const dout = outW.some((x) => x < STROKE_CHAMFER_MAX) ? distOutside(s, true) : null;
|
|
1754
|
-
const doutExact = outW.some((x) => x >= STROKE_CHAMFER_MAX) ? distOutside(s, false) : null;
|
|
1755
|
-
for (const d of [din, dout, doutExact]) if (d) bytes += d.byteLength;
|
|
1756
|
-
return { rect, items, bounds, shape, per, bevelPaint, din, dout, doutExact, frames, bytes };
|
|
1587
|
+
t = clamp012(t);
|
|
1588
|
+
return reverse ? 1 - t : t;
|
|
1757
1589
|
}
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
const
|
|
1762
|
-
const
|
|
1763
|
-
const
|
|
1764
|
-
|
|
1590
|
+
function gradientLayout(style, angle, scale, offset, frame) {
|
|
1591
|
+
const unchanged = [angle, scale, offset];
|
|
1592
|
+
if (style !== "linear" && style !== "reflected" || ![angle, scale, offset.x, offset.y].every(Number.isFinite)) return unchanged;
|
|
1593
|
+
const w = Math.max(frame.width, 1);
|
|
1594
|
+
const h = Math.max(frame.height, 1);
|
|
1595
|
+
const cx = frame.x + w / 2 + offset.x * w;
|
|
1596
|
+
const cy = frame.y + h / 2 + offset.y * h;
|
|
1597
|
+
const chordOf = (r) => Math.max(Math.min(w / Math.max(Math.abs(Math.cos(r)), 1e-6), h / Math.max(Math.abs(Math.sin(r)), 1e-6)), 1);
|
|
1598
|
+
const a = angle * Math.PI / 180;
|
|
1599
|
+
const half = chordOf(a) * Math.max(scale, 1e-3) / 2;
|
|
1600
|
+
const dx = Math.cos(a) * half;
|
|
1601
|
+
const dy = -Math.sin(a) * half;
|
|
1602
|
+
const snap2 = (v2) => Math.floor(v2 + 1e-4);
|
|
1603
|
+
const end = [snap2(cx + dx), snap2(cy + dy)];
|
|
1604
|
+
let start;
|
|
1605
|
+
let mid;
|
|
1606
|
+
if (style === "reflected") {
|
|
1607
|
+
start = [cx, cy];
|
|
1608
|
+
mid = [cx, cy];
|
|
1609
|
+
} else {
|
|
1610
|
+
start = [snap2(cx - dx), snap2(cy - dy)];
|
|
1611
|
+
mid = [(start[0] + end[0]) / 2, (start[1] + end[1]) / 2];
|
|
1612
|
+
}
|
|
1613
|
+
const v = [end[0] - start[0], end[1] - start[1]];
|
|
1614
|
+
const len = Math.hypot(v[0], v[1]);
|
|
1615
|
+
if (len < 0.5) return unchanged;
|
|
1616
|
+
const a2 = Math.atan2(-v[1], v[0]);
|
|
1617
|
+
const span = style === "reflected" ? 2 * len : len;
|
|
1618
|
+
return [a2 * 180 / Math.PI, span / chordOf(a2), { x: offset.x + (mid[0] - cx) / w, y: offset.y + (mid[1] - cy) / h }];
|
|
1765
1619
|
}
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
const
|
|
1769
|
-
const
|
|
1770
|
-
|
|
1620
|
+
function paintGradient(dst, m, g, frame, env, mode, opacity) {
|
|
1621
|
+
const prepared = new PreparedGradient(g);
|
|
1622
|
+
const [angle, scale, offset] = gradientLayout(g.style, g.angle, g.scale, g.offset, frame);
|
|
1623
|
+
const { x: rx, y: ry, width: w } = env.rect;
|
|
1624
|
+
paint(dst, m, (i, c) => prepared.sample(gradientT(g.style, angle, scale, g.reverse, offset, frame, rx + i % w + 0.5, ry + Math.floor(i / w) + 0.5), c), mode, opacity);
|
|
1771
1625
|
}
|
|
1772
|
-
function
|
|
1773
|
-
const
|
|
1774
|
-
if (!
|
|
1775
|
-
const
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1626
|
+
function paintPattern(dst, m, p, env, mode, opacity) {
|
|
1627
|
+
const tile = env.ctx.pattern(p.patternId);
|
|
1628
|
+
if (!tile) return;
|
|
1629
|
+
const place = new PatternPlacement(env.anchor, _nullishCoalesce(p.link, () => ( true)), _nullishCoalesce(p.phase, () => ( { x: 0, y: 0 })), p.scale, _nullishCoalesce(p.angle, () => ( 0)));
|
|
1630
|
+
const { x: rx, y: ry, width: w } = env.rect;
|
|
1631
|
+
const uv = [0, 0];
|
|
1632
|
+
paint(
|
|
1633
|
+
dst,
|
|
1634
|
+
m,
|
|
1635
|
+
(i, c) => {
|
|
1636
|
+
place.map(rx + i % w + 0.5, ry + Math.floor(i / w) + 0.5, uv);
|
|
1637
|
+
tile.sample(uv[0], uv[1], c);
|
|
1638
|
+
},
|
|
1639
|
+
mode,
|
|
1640
|
+
opacity
|
|
1641
|
+
);
|
|
1782
1642
|
}
|
|
1783
|
-
function
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
}
|
|
1643
|
+
function paintFill(dst, m, f, frame, env, mode, opacity) {
|
|
1644
|
+
if (f.type === "color") paintColor(dst, m, f.color, mode, opacity);
|
|
1645
|
+
else if (f.type === "gradient") paintGradient(dst, m, f.gradient, f.gradient.align ? frame : env.canvas, env, mode, opacity);
|
|
1646
|
+
else paintPattern(dst, m, f, env, mode, opacity);
|
|
1788
1647
|
}
|
|
1789
|
-
function
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1648
|
+
function effectFillColors(fill2, rect, frame, canvas, anchor, ctx) {
|
|
1649
|
+
const n = rect.width * rect.height;
|
|
1650
|
+
const out = new Float32Array(n * 4);
|
|
1651
|
+
const c = [0, 0, 0, 1];
|
|
1652
|
+
const { x: rx, y: ry, width: w } = rect;
|
|
1653
|
+
if (fill2.type === "color") {
|
|
1654
|
+
const [r, g, b] = rgbOf(fill2.color);
|
|
1655
|
+
for (let i = 0; i < n * 4; i += 4) {
|
|
1656
|
+
out[i] = r;
|
|
1657
|
+
out[i + 1] = g;
|
|
1658
|
+
out[i + 2] = b;
|
|
1659
|
+
out[i + 3] = 1;
|
|
1660
|
+
}
|
|
1661
|
+
return out;
|
|
1795
1662
|
}
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
merged = true;
|
|
1805
|
-
break;
|
|
1806
|
-
}
|
|
1807
|
-
}
|
|
1663
|
+
if (fill2.type === "gradient") {
|
|
1664
|
+
const gr = fill2.gradient;
|
|
1665
|
+
const f = gr.align ? frame : canvas;
|
|
1666
|
+
const prepared = new PreparedGradient(gr);
|
|
1667
|
+
const [angle, scale, offset] = gradientLayout(gr.style, gr.angle, gr.scale, gr.offset, f);
|
|
1668
|
+
for (let i = 0; i < n; i++) {
|
|
1669
|
+
prepared.sample(gradientT(gr.style, angle, scale, gr.reverse, offset, f, rx + i % w + 0.5, ry + Math.floor(i / w) + 0.5), c);
|
|
1670
|
+
out.set(c, i * 4);
|
|
1808
1671
|
}
|
|
1672
|
+
return out;
|
|
1809
1673
|
}
|
|
1810
|
-
const
|
|
1811
|
-
if (
|
|
1812
|
-
const
|
|
1813
|
-
const
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
const w = windows[k];
|
|
1821
|
-
const part = buildEffectMaps(items, shapeOver(w), w, ctx);
|
|
1822
|
-
pasteMap(shape, rect, part.shape, w, a);
|
|
1823
|
-
per.forEach((maps, i) => maps.forEach((m, j) => pasteMap(m, rect, part.per[i][j], w, a)));
|
|
1824
|
-
if (din) pasteMap(din, rect, part.din, w, a);
|
|
1825
|
-
if (dout) pasteMap(dout, rect, part.dout, w, a);
|
|
1826
|
-
if (doutExact) pasteMap(doutExact, rect, part.doutExact, w, a);
|
|
1827
|
-
});
|
|
1828
|
-
let bytes = shape.byteLength;
|
|
1829
|
-
for (const maps of per) for (const m of maps) bytes += m.byteLength;
|
|
1830
|
-
for (const d of [din, dout, doutExact]) if (d) bytes += d.byteLength;
|
|
1831
|
-
return { rect, items, bounds: shapeBounds(shape, rect), shape, per, bevelPaint: prev.bevelPaint, din, dout, doutExact, frames: /* @__PURE__ */ new Map(), bytes };
|
|
1674
|
+
const tile = ctx.pattern(fill2.patternId);
|
|
1675
|
+
if (!tile) return out;
|
|
1676
|
+
const place = new PatternPlacement(anchor, _nullishCoalesce(fill2.link, () => ( true)), _nullishCoalesce(fill2.phase, () => ( { x: 0, y: 0 })), fill2.scale, _nullishCoalesce(fill2.angle, () => ( 0)));
|
|
1677
|
+
const uv = [0, 0];
|
|
1678
|
+
for (let i = 0; i < n; i++) {
|
|
1679
|
+
place.map(rx + i % w + 0.5, ry + Math.floor(i / w) + 0.5, uv);
|
|
1680
|
+
tile.sample(uv[0], uv[1], c);
|
|
1681
|
+
out.set(c, i * 4);
|
|
1682
|
+
}
|
|
1683
|
+
return out;
|
|
1832
1684
|
}
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
const
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1685
|
+
function paintGlow(dst, m, g, env) {
|
|
1686
|
+
if (g.fill.type === "color") return paintColor(dst, m, g.fill.color, g.blend, g.opacity);
|
|
1687
|
+
const prepared = new PreparedGradient(g.fill.gradient);
|
|
1688
|
+
const r = Number.isFinite(g.range) ? clamp(g.range, 0.01, 1) : 1;
|
|
1689
|
+
const gain = 1 / (r * r);
|
|
1690
|
+
const strength = new Float32Array(m.length);
|
|
1691
|
+
for (let i = 0; i < m.length; i++) strength[i] = Math.min(m[i] * gain, 1);
|
|
1692
|
+
paint(dst, strength, (i, c) => prepared.sample(1 - clamp012(m[i]), c), g.blend, g.opacity);
|
|
1693
|
+
}
|
|
1694
|
+
function crop(v, from, to, fill2) {
|
|
1695
|
+
const out = new Float32Array(to.width * to.height);
|
|
1696
|
+
if (fill2) out.fill(fill2);
|
|
1697
|
+
const ix0 = Math.max(from.x, to.x);
|
|
1698
|
+
const iy0 = Math.max(from.y, to.y);
|
|
1699
|
+
const ix1 = Math.min(from.x + from.width, to.x + to.width);
|
|
1700
|
+
const iy1 = Math.min(from.y + from.height, to.y + to.height);
|
|
1701
|
+
if (ix1 <= ix0 || iy1 <= iy0) return out;
|
|
1702
|
+
const n = ix1 - ix0;
|
|
1703
|
+
for (let y = iy0; y < iy1; y++) {
|
|
1704
|
+
const s = (y - from.y) * from.width + (ix0 - from.x);
|
|
1705
|
+
out.set(v.subarray(s, s + n), (y - to.y) * to.width + (ix0 - to.x));
|
|
1843
1706
|
}
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1707
|
+
return out;
|
|
1708
|
+
}
|
|
1709
|
+
function compositeLayerEffects(input) {
|
|
1710
|
+
const { backdrop, content, rect, maps, ctx } = input;
|
|
1711
|
+
const items = maps.items;
|
|
1712
|
+
const n = rect.width * rect.height;
|
|
1713
|
+
const cs = content instanceof Float32Array ? 1 : 1 / 255;
|
|
1714
|
+
const bs = backdrop instanceof Float32Array ? 1 : 1 / 255;
|
|
1715
|
+
const floatOut = backdrop instanceof Float32Array;
|
|
1716
|
+
const shape = new Float32Array(n);
|
|
1717
|
+
for (let i = 0; i < n; i++) shape[i] = content[i * 4 + 3] * cs;
|
|
1718
|
+
const before = new Float32Array(n * 4);
|
|
1719
|
+
for (let i = 0; i < n * 4; i++) before[i] = backdrop[i] * bs;
|
|
1720
|
+
const work = new Float32Array(before);
|
|
1721
|
+
const fx = (i, k) => crop(maps.per[i][k], maps.rect, rect, 0);
|
|
1722
|
+
const bounds = _nullishCoalesce(maps.bounds, () => ( rect));
|
|
1723
|
+
const env = { rect, bounds, canvas: input.canvas, anchor: { x: bounds.x, y: bounds.y }, ctx };
|
|
1724
|
+
const fill2 = clamp012(input.fillOpacity);
|
|
1725
|
+
const inside = (a) => a > INSIDE_EPS;
|
|
1726
|
+
const rev = [];
|
|
1727
|
+
for (let i = items.length - 1; i >= 0; i--) rev.push(i);
|
|
1728
|
+
const knockOut = (m, fillOpacity) => {
|
|
1729
|
+
const seeThrough = 1 - clamp012(fillOpacity);
|
|
1730
|
+
for (let i = 0; i < n; i++) m[i] *= 1 - shape[i] * seeThrough;
|
|
1731
|
+
};
|
|
1732
|
+
const normalLike = input.blend === "normal";
|
|
1733
|
+
for (const i of rev) {
|
|
1734
|
+
const e = items[i];
|
|
1735
|
+
if (e.kind !== "drop-shadow") continue;
|
|
1736
|
+
const m = fx(i, 0);
|
|
1737
|
+
if (e.knocksOut) knockOut(m, normalLike ? fill2 : 0);
|
|
1738
|
+
paintColor(work, m, e.color, e.blend, e.opacity);
|
|
1860
1739
|
}
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
m2 = sb;
|
|
1868
|
-
} else if (separable) {
|
|
1869
|
-
m0 = _chunk7ISPWEJAcjs.blendChannel.call(void 0, mode, b0, sr);
|
|
1870
|
-
m1 = _chunk7ISPWEJAcjs.blendChannel.call(void 0, mode, b1, sg);
|
|
1871
|
-
m2 = _chunk7ISPWEJAcjs.blendChannel.call(void 0, mode, b2, sb);
|
|
1872
|
-
} else {
|
|
1873
|
-
rgbScratchB[0] = b0;
|
|
1874
|
-
rgbScratchB[1] = b1;
|
|
1875
|
-
rgbScratchB[2] = b2;
|
|
1876
|
-
rgbScratchS[0] = sr;
|
|
1877
|
-
rgbScratchS[1] = sg;
|
|
1878
|
-
rgbScratchS[2] = sb;
|
|
1879
|
-
const m = _chunk7ISPWEJAcjs.blendRgb.call(void 0, mode, rgbScratchB, rgbScratchS);
|
|
1880
|
-
m0 = m[0];
|
|
1881
|
-
m1 = m[1];
|
|
1882
|
-
m2 = m[2];
|
|
1740
|
+
for (const i of rev) {
|
|
1741
|
+
const e = items[i];
|
|
1742
|
+
if (e.kind !== "outer-glow") continue;
|
|
1743
|
+
const m = fx(i, 0);
|
|
1744
|
+
knockOut(m, fill2);
|
|
1745
|
+
paintGlow(work, m, e, env);
|
|
1883
1746
|
}
|
|
1884
|
-
const
|
|
1885
|
-
const ws = (1 - ab) * sa;
|
|
1886
|
-
const wm = sa * ab;
|
|
1887
|
-
dst[i] = (wb * b0 + ws * sr + wm * m0) / ao;
|
|
1888
|
-
dst[i + 1] = (wb * b1 + ws * sg + wm * m1) / ao;
|
|
1889
|
-
dst[i + 2] = (wb * b2 + ws * sb + wm * m2) / ao;
|
|
1890
|
-
dst[i + 3] = ao;
|
|
1891
|
-
}
|
|
1892
|
-
function paint(dst, m, color2, mode, opacity) {
|
|
1893
|
-
const sep = mode !== "normal" && _chunk7ISPWEJAcjs.isSeparableBlendMode.call(void 0, mode);
|
|
1894
|
-
const c = [0, 0, 0, 1];
|
|
1895
|
-
const n = m.length;
|
|
1747
|
+
const lay = new Float32Array(n * 4);
|
|
1896
1748
|
for (let i = 0; i < n; i++) {
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1749
|
+
lay[i * 4] = content[i * 4] * cs;
|
|
1750
|
+
lay[i * 4 + 1] = content[i * 4 + 1] * cs;
|
|
1751
|
+
lay[i * 4 + 2] = content[i * 4 + 2] * cs;
|
|
1752
|
+
lay[i * 4 + 3] = inside(shape[i]) ? fill2 : 0;
|
|
1753
|
+
}
|
|
1754
|
+
const premerge = !normalLike;
|
|
1755
|
+
if (premerge) {
|
|
1756
|
+
const sep2 = _chunk7ISPWEJAcjs.isSeparableBlendMode.call(void 0, input.blend);
|
|
1757
|
+
for (let i = 0; i < n; i++) {
|
|
1758
|
+
const p = i * 4;
|
|
1759
|
+
const sr = lay[p];
|
|
1760
|
+
const sg = lay[p + 1];
|
|
1761
|
+
const sb = lay[p + 2];
|
|
1762
|
+
const sa = lay[p + 3];
|
|
1763
|
+
lay[p] = work[p];
|
|
1764
|
+
lay[p + 1] = work[p + 1];
|
|
1765
|
+
lay[p + 2] = work[p + 2];
|
|
1766
|
+
lay[p + 3] = work[p + 3];
|
|
1767
|
+
compositeAt(lay, p, input.blend, sep2, sr, sg, sb, sa);
|
|
1768
|
+
}
|
|
1769
|
+
}
|
|
1770
|
+
const rel = (m) => {
|
|
1771
|
+
for (let i = 0; i < n; i++) m[i] = inside(shape[i]) ? Math.min(m[i] / shape[i], 1) : 0;
|
|
1772
|
+
return m;
|
|
1773
|
+
};
|
|
1774
|
+
const full = new Float32Array(n);
|
|
1775
|
+
for (let i = 0; i < n; i++) full[i] = inside(shape[i]) ? 1 : 0;
|
|
1776
|
+
for (const i of rev) {
|
|
1777
|
+
const e = items[i];
|
|
1778
|
+
if (e.kind === "pattern-overlay") paintPattern(lay, full, e, env, e.blend, e.opacity);
|
|
1779
|
+
}
|
|
1780
|
+
for (const i of rev) {
|
|
1781
|
+
const e = items[i];
|
|
1782
|
+
if (e.kind === "gradient-overlay") paintGradient(lay, full, e.gradient, e.gradient.align ? bounds : input.canvas, env, e.blend, e.opacity);
|
|
1783
|
+
}
|
|
1784
|
+
for (const i of rev) {
|
|
1785
|
+
const e = items[i];
|
|
1786
|
+
if (e.kind === "color-overlay") paintColor(lay, full, e.color, e.blend, e.opacity);
|
|
1787
|
+
}
|
|
1788
|
+
for (const i of rev) {
|
|
1789
|
+
const e = items[i];
|
|
1790
|
+
if (e.kind === "satin") paintColor(lay, rel(fx(i, 0)), e.color, e.blend, e.opacity);
|
|
1791
|
+
}
|
|
1792
|
+
for (const i of rev) {
|
|
1793
|
+
const e = items[i];
|
|
1794
|
+
if (e.kind === "inner-glow") paintGlow(lay, rel(fx(i, 0)), e, env);
|
|
1795
|
+
}
|
|
1796
|
+
for (const i of rev) {
|
|
1797
|
+
const e = items[i];
|
|
1798
|
+
if (e.kind === "inner-shadow") paintColor(lay, rel(fx(i, 0)), e.color, e.blend, e.opacity);
|
|
1799
|
+
}
|
|
1800
|
+
const strokeIdx = items.map((e, i) => e.kind === "stroke" ? i : -1).filter((i) => i >= 0);
|
|
1801
|
+
const din = strokeIdx.length && maps.din ? crop(maps.din, maps.rect, rect, 0) : null;
|
|
1802
|
+
const frameOf = (i) => _nullishCoalesce(maps.frames.get(i), () => ( bounds));
|
|
1803
|
+
for (let k = strokeIdx.length - 1; k >= 0; k--) {
|
|
1804
|
+
const st = items[strokeIdx[k]];
|
|
1805
|
+
const [inW] = strokeWidths(st);
|
|
1806
|
+
if (!(inW > 0) || !din) continue;
|
|
1807
|
+
const m = new Float32Array(n);
|
|
1808
|
+
for (let i = 0; i < n; i++) m[i] = inside(shape[i]) ? clamp012(inW + 0.5 - din[i]) : 0;
|
|
1809
|
+
paintFill(lay, m, st.fill, frameOf(strokeIdx[k]), env, st.blend, st.opacity);
|
|
1810
|
+
}
|
|
1811
|
+
for (const i of rev) {
|
|
1812
|
+
const e = items[i];
|
|
1813
|
+
if (e.kind !== "bevel-emboss" || maps.bevelPaint[i] !== "inner") continue;
|
|
1814
|
+
paintColor(lay, rel(fx(i, 0)), e.highlightColor, e.highlightBlend, e.highlightOpacity);
|
|
1815
|
+
paintColor(lay, rel(fx(i, 1)), e.shadowColor, e.shadowBlend, e.shadowOpacity);
|
|
1816
|
+
}
|
|
1817
|
+
for (let i = 0; i < n; i++) lay[i * 4 + 3] *= Math.min(shape[i], 1);
|
|
1818
|
+
const outside = strokeIdx.filter((i) => strokeWidths(items[i])[1] > 0);
|
|
1819
|
+
if (outside.length) {
|
|
1820
|
+
const dout = maps.dout ? crop(maps.dout, maps.rect, rect, FAR) : null;
|
|
1821
|
+
const doutExact = maps.doutExact ? crop(maps.doutExact, maps.rect, rect, FAR) : null;
|
|
1822
|
+
const base = new Float32Array(work);
|
|
1823
|
+
const acc = new Float32Array(n * 4);
|
|
1824
|
+
const cover = new Float32Array(n);
|
|
1825
|
+
for (const si of outside) {
|
|
1826
|
+
const st = items[si];
|
|
1827
|
+
const outW = strokeWidths(st)[1];
|
|
1828
|
+
const d = _nullishCoalesce((outW >= STROKE_CHAMFER_MAX ? doutExact : dout), () => ( new Float32Array(n).fill(FAR)));
|
|
1829
|
+
const share = new Float32Array(n);
|
|
1830
|
+
const ones = new Float32Array(n);
|
|
1831
|
+
for (let i = 0; i < n; i++) {
|
|
1832
|
+
const band = clamp012(outW + 0.5 - d[i]);
|
|
1833
|
+
let k;
|
|
1834
|
+
if (inside(shape[i])) {
|
|
1835
|
+
const c = clamp012(lay[i * 4 + 3]);
|
|
1836
|
+
k = c >= 1 ? 1 : clamp012((1 - clamp012(shape[i])) / (1 - c));
|
|
1837
|
+
} else k = band;
|
|
1838
|
+
share[i] = k * st.opacity * (1 - cover[i]);
|
|
1839
|
+
cover[i] += share[i];
|
|
1840
|
+
ones[i] = share[i] > 0 ? 1 : 0;
|
|
1841
|
+
}
|
|
1842
|
+
const blended = new Float32Array(base);
|
|
1843
|
+
paintFill(blended, ones, st.fill, frameOf(si), env, st.blend, 1);
|
|
1844
|
+
for (let i = 0; i < n; i++) {
|
|
1845
|
+
const s = share[i];
|
|
1846
|
+
if (!(s > 0)) continue;
|
|
1847
|
+
const p = i * 4;
|
|
1848
|
+
const ba = blended[p + 3];
|
|
1849
|
+
acc[p] += s * blended[p] * ba;
|
|
1850
|
+
acc[p + 1] += s * blended[p + 1] * ba;
|
|
1851
|
+
acc[p + 2] += s * blended[p + 2] * ba;
|
|
1852
|
+
acc[p + 3] += s * ba;
|
|
1853
|
+
}
|
|
1854
|
+
}
|
|
1855
|
+
for (let i = 0; i < n; i++) {
|
|
1856
|
+
const c = cover[i];
|
|
1857
|
+
if (c <= 0) continue;
|
|
1858
|
+
const p = i * 4;
|
|
1859
|
+
const k = 1 - Math.min(c, 1);
|
|
1860
|
+
const a = work[p + 3] * k + acc[p + 3];
|
|
1861
|
+
if (a > 0) {
|
|
1862
|
+
work[p] = (work[p] * work[p + 3] * k + acc[p]) / a;
|
|
1863
|
+
work[p + 1] = (work[p + 1] * work[p + 3] * k + acc[p + 1]) / a;
|
|
1864
|
+
work[p + 2] = (work[p + 2] * work[p + 3] * k + acc[p + 2]) / a;
|
|
1865
|
+
work[p + 3] = Math.min(a, 1);
|
|
1866
|
+
}
|
|
1867
|
+
}
|
|
1868
|
+
}
|
|
1869
|
+
for (const i of rev) {
|
|
1870
|
+
const e = items[i];
|
|
1871
|
+
if (e.kind !== "bevel-emboss" || maps.bevelPaint[i] !== "outer") continue;
|
|
1872
|
+
paintColor(work, fx(i, 0), e.highlightColor, e.highlightBlend, e.highlightOpacity);
|
|
1873
|
+
paintColor(work, fx(i, 1), e.shadowColor, e.shadowBlend, e.shadowOpacity);
|
|
1874
|
+
}
|
|
1875
|
+
const mode = premerge ? "normal" : input.blend;
|
|
1876
|
+
const sep = _chunk7ISPWEJAcjs.isSeparableBlendMode.call(void 0, mode);
|
|
1877
|
+
for (let i = 0; i < n; i++) {
|
|
1878
|
+
const p = i * 4;
|
|
1879
|
+
if (lay[p + 3] > 0) compositeAt(work, p, mode, sep, lay[p], lay[p + 1], lay[p + 2], lay[p + 3]);
|
|
1880
|
+
}
|
|
1881
|
+
for (const i of rev) {
|
|
1882
|
+
const e = items[i];
|
|
1883
|
+
if (e.kind !== "bevel-emboss" || maps.bevelPaint[i] !== "both") continue;
|
|
1884
|
+
paintColor(work, fx(i, 0), e.highlightColor, e.highlightBlend, e.highlightOpacity);
|
|
1885
|
+
paintColor(work, fx(i, 1), e.shadowColor, e.shadowBlend, e.shadowOpacity);
|
|
1886
|
+
}
|
|
1887
|
+
const op = clamp012(input.opacity);
|
|
1888
|
+
for (let i = 0; i < n; i++) {
|
|
1889
|
+
const p = i * 4;
|
|
1890
|
+
const aa = before[p + 3];
|
|
1891
|
+
const ba = work[p + 3];
|
|
1892
|
+
const alpha = aa + (ba - aa) * op;
|
|
1893
|
+
if (alpha <= 0) {
|
|
1894
|
+
backdrop[p] = backdrop[p + 1] = backdrop[p + 2] = backdrop[p + 3] = 0;
|
|
1895
|
+
continue;
|
|
1896
|
+
}
|
|
1897
|
+
if (floatOut) {
|
|
1898
|
+
for (let c = 0; c < 3; c++) backdrop[p + c] = (before[p + c] * aa + (work[p + c] * ba - before[p + c] * aa) * op) / alpha;
|
|
1899
|
+
backdrop[p + 3] = alpha;
|
|
1900
|
+
continue;
|
|
1901
|
+
}
|
|
1902
|
+
for (let c = 0; c < 3; c++) backdrop[p + c] = Math.round((before[p + c] * aa + (work[p + c] * ba - before[p + c] * aa) * op) / alpha * 255);
|
|
1903
|
+
backdrop[p + 3] = Math.round(alpha * 255);
|
|
1901
1904
|
}
|
|
1902
1905
|
}
|
|
1903
|
-
function
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
);
|
|
1906
|
+
function renderLayerEffects(effects, layer, backdrop, canvas, ctx) {
|
|
1907
|
+
const items = activeEffectItems(effects);
|
|
1908
|
+
const n = layer.rect.width * layer.rect.height;
|
|
1909
|
+
const shape = new Float32Array(n);
|
|
1910
|
+
for (let i = 0; i < n; i++) shape[i] = layer.content[i * 4 + 3] / 255;
|
|
1911
|
+
const maps = buildEffectMaps(items, shape, layer.rect, ctx);
|
|
1912
|
+
compositeLayerEffects({
|
|
1913
|
+
backdrop,
|
|
1914
|
+
content: layer.content,
|
|
1915
|
+
rect: layer.rect,
|
|
1916
|
+
maps,
|
|
1917
|
+
blend: layer.blend,
|
|
1918
|
+
opacity: layer.opacity,
|
|
1919
|
+
fillOpacity: _nullishCoalesce(layer.fillOpacity, () => ( 1)),
|
|
1920
|
+
canvas,
|
|
1921
|
+
ctx
|
|
1922
|
+
});
|
|
1920
1923
|
}
|
|
1921
|
-
|
|
1924
|
+
|
|
1925
|
+
// src/raster/deep-compositor.ts
|
|
1926
|
+
var isGroup = (l) => l.type === "group";
|
|
1927
|
+
var DeepCompositor = class {
|
|
1928
|
+
constructor(base, profile, deep, depth) {
|
|
1929
|
+
this.base = base;
|
|
1930
|
+
this.profile = profile;
|
|
1931
|
+
this.deep = deep;
|
|
1932
|
+
this.depth = depth;
|
|
1933
|
+
this.linear = depth === 32;
|
|
1934
|
+
}
|
|
1922
1935
|
|
|
1923
1936
|
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1937
|
+
|
|
1938
|
+
|
|
1939
|
+
|
|
1940
|
+
|
|
1941
|
+
/** The composite of `layers` over `rect` as float RGBA in the working space (`rect.width × rect.height × 4`). */
|
|
1942
|
+
composite(layers, rect, sources) {
|
|
1943
|
+
this.sources = sources;
|
|
1944
|
+
const acc = new Float32Array(Math.max(0, rect.width * rect.height * 4));
|
|
1945
|
+
if (rect.width > 0 && rect.height > 0) this.runSteps(this.buildSteps(layers), acc, true, rect);
|
|
1946
|
+
return acc;
|
|
1927
1947
|
}
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
const f = b[0] > a2[0] ? (t - a2[0]) / (b[0] - a2[0]) : 0;
|
|
1943
|
-
out[0] = a2[1] + (b[1] - a2[1]) * f;
|
|
1944
|
-
out[1] = a2[2] + (b[2] - a2[2]) * f;
|
|
1945
|
-
out[2] = a2[3] + (b[3] - a2[3]) * f;
|
|
1946
|
-
done = true;
|
|
1947
|
-
break;
|
|
1948
|
-
}
|
|
1949
|
-
}
|
|
1950
|
-
if (!done) {
|
|
1951
|
-
const l = c[c.length - 1];
|
|
1952
|
-
out[0] = l[1];
|
|
1953
|
-
out[1] = l[2];
|
|
1954
|
-
out[2] = l[3];
|
|
1948
|
+
// --- Steps (as RasterCompositor.buildSteps) ------------------------------------
|
|
1949
|
+
isPixel(l) {
|
|
1950
|
+
return l.type === "pixel" || (_nullishCoalesce(_optionalChain([this, 'access', _2 => _2.profile, 'access', _3 => _3.isPixelLike, 'optionalCall', _4 => _4(l)]), () => ( false)));
|
|
1951
|
+
}
|
|
1952
|
+
isFilter(l) {
|
|
1953
|
+
return _nullishCoalesce(_optionalChain([this, 'access', _5 => _5.profile, 'access', _6 => _6.isFilterLayer, 'optionalCall', _7 => _7(l)]), () => ( false));
|
|
1954
|
+
}
|
|
1955
|
+
buildSteps(layers) {
|
|
1956
|
+
const steps = [];
|
|
1957
|
+
for (const layer of layers) {
|
|
1958
|
+
const last = steps[steps.length - 1];
|
|
1959
|
+
if (layer.clipped && last && (last.kind === "content" || last.kind === "group")) {
|
|
1960
|
+
last.clipped.push(layer);
|
|
1961
|
+
continue;
|
|
1955
1962
|
}
|
|
1963
|
+
if (this.isFilter(layer)) {
|
|
1964
|
+
if (last && last.kind === "adjust") last.layers.push(layer);
|
|
1965
|
+
else steps.push({ kind: "adjust", layers: [layer] });
|
|
1966
|
+
} else if (isGroup(layer)) steps.push({ kind: "group", layer, clipped: [], steps: this.buildSteps(_nullishCoalesce(layer.children, () => ( []))) });
|
|
1967
|
+
else steps.push({ kind: "content", layer, clipped: [] });
|
|
1956
1968
|
}
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1969
|
+
return steps;
|
|
1970
|
+
}
|
|
1971
|
+
runSteps(steps, acc, empty, r) {
|
|
1972
|
+
for (const s of steps) empty = this.runStep(s, acc, empty, r);
|
|
1973
|
+
return empty;
|
|
1974
|
+
}
|
|
1975
|
+
runStep(step, acc, empty, r) {
|
|
1976
|
+
if (step.kind === "adjust") {
|
|
1977
|
+
if (empty) return true;
|
|
1978
|
+
this.applyFilterRun(step.layers, acc, r);
|
|
1979
|
+
return false;
|
|
1980
|
+
}
|
|
1981
|
+
const layer = step.layer;
|
|
1982
|
+
if (!layer.visible) return empty;
|
|
1983
|
+
const clipped = step.clipped.filter((l) => l.visible);
|
|
1984
|
+
if (step.kind === "content" && this.deepEffects(layer)) return this.runEffects(layer, clipped, acc, r) ? false : empty;
|
|
1985
|
+
const coverage = this.renderedAlone(layer) ? null : this.base.maskCoverage(layer, r, this.sources);
|
|
1986
|
+
if (coverage && coverage.every((v) => v <= 0)) return empty;
|
|
1987
|
+
if (step.kind === "group" && !this.renderedAlone(layer)) {
|
|
1988
|
+
if (layer.blend === "pass-through" && !clipped.length) {
|
|
1989
|
+
if (layer.opacity >= 1 && !coverage) return this.runSteps(step.steps, acc, empty, r);
|
|
1990
|
+
const before = acc.slice();
|
|
1991
|
+
const stillEmpty = this.runSteps(step.steps, acc, empty, r);
|
|
1992
|
+
lerp(acc, before, layer.opacity, coverage);
|
|
1993
|
+
return empty && stillEmpty;
|
|
1968
1994
|
}
|
|
1995
|
+
const buf2 = new Float32Array(acc.length);
|
|
1996
|
+
if (this.runSteps(step.steps, buf2, true, r)) return empty;
|
|
1997
|
+
this.applyClipped(clipped, buf2, r);
|
|
1998
|
+
const mode2 = layer.blend === "pass-through" ? "normal" : layer.blend;
|
|
1999
|
+
this.blend(acc, buf2, mode2, layer.opacity, coverage);
|
|
2000
|
+
return false;
|
|
2001
|
+
}
|
|
2002
|
+
const content = this.content(layer, r);
|
|
2003
|
+
if (!content) return empty;
|
|
2004
|
+
const alone = this.renderedAlone(layer);
|
|
2005
|
+
const fill2 = !alone && this.isPixel(layer) ? _nullishCoalesce(layer.fillOpacity, () => ( 1)) : 1;
|
|
2006
|
+
const mode = this.blendOf(layer);
|
|
2007
|
+
if (!clipped.length) {
|
|
2008
|
+
this.blend(acc, content, mode, layer.opacity * fill2, coverage);
|
|
2009
|
+
return false;
|
|
1969
2010
|
}
|
|
2011
|
+
const buf = new Float32Array(acc.length);
|
|
2012
|
+
this.blend(buf, content, "normal", fill2, coverage);
|
|
2013
|
+
this.applyClipped(clipped, buf, r);
|
|
2014
|
+
this.blend(acc, buf, mode, layer.opacity, null);
|
|
2015
|
+
return false;
|
|
1970
2016
|
}
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
const dy = y - cy;
|
|
1990
|
-
const along = dx * c - dy * s;
|
|
1991
|
-
const across = dx * s + dy * c;
|
|
1992
|
-
let [chord, len] = gradientUnits(angle, w, h);
|
|
1993
|
-
chord *= Math.max(scale, 1e-3);
|
|
1994
|
-
len *= Math.max(scale, 1e-3);
|
|
1995
|
-
const corner = 0.5 * (c - s);
|
|
1996
|
-
let t;
|
|
1997
|
-
switch (style) {
|
|
1998
|
-
case "linear":
|
|
1999
|
-
t = (along - corner) / chord + 0.5;
|
|
2000
|
-
break;
|
|
2001
|
-
case "reflected":
|
|
2002
|
-
t = Math.abs((along - corner) / (chord / 2));
|
|
2003
|
-
break;
|
|
2004
|
-
case "radial":
|
|
2005
|
-
t = Math.sqrt(dx * dx + dy * dy) / (len / 2);
|
|
2006
|
-
break;
|
|
2007
|
-
case "diamond":
|
|
2008
|
-
t = (Math.abs(along) + Math.abs(across)) / (len / 2);
|
|
2009
|
-
break;
|
|
2010
|
-
case "angle": {
|
|
2011
|
-
const turn = (a - Math.atan2(-dy, dx)) / (2 * Math.PI);
|
|
2012
|
-
t = turn - Math.floor(turn);
|
|
2013
|
-
break;
|
|
2017
|
+
/**
|
|
2018
|
+
* A pixel layer with effects onto `acc` over `r`: its deep content (filters, mask, clipped
|
|
2019
|
+
* layers) and the effects composited in float. Effect maps come from the 8-bit shape. At 32
|
|
2020
|
+
* bits the effects composite in sRGB-encoded values (their colours and blends are defined
|
|
2021
|
+
* there) and the result is decoded back. Returns whether anything was drawn.
|
|
2022
|
+
*/
|
|
2023
|
+
runEffects(layer, clipped, acc, r) {
|
|
2024
|
+
const fx = this.base.effectsInput(layer, r, this.sources);
|
|
2025
|
+
if (!fx) return false;
|
|
2026
|
+
const a = fx.rect;
|
|
2027
|
+
const content = _nullishCoalesce(this.content(layer, a), () => ( new Float32Array(a.width * a.height * 4)));
|
|
2028
|
+
const coverage = this.base.maskCoverage(layer, a, this.sources);
|
|
2029
|
+
if (coverage) for (let i = 0; i < coverage.length; i++) content[i * 4 + 3] *= coverage[i];
|
|
2030
|
+
if (clipped.length) this.applyClipped(clipped, content, a);
|
|
2031
|
+
const sub = new Float32Array(a.width * a.height * 4);
|
|
2032
|
+
for (let y = 0; y < a.height; y++) {
|
|
2033
|
+
const s = ((a.y - r.y + y) * r.width + (a.x - r.x)) * 4;
|
|
2034
|
+
sub.set(acc.subarray(s, s + a.width * 4), y * a.width * 4);
|
|
2014
2035
|
}
|
|
2036
|
+
if (this.linear) {
|
|
2037
|
+
encodeInPlace(sub);
|
|
2038
|
+
encodeInPlace(content);
|
|
2039
|
+
}
|
|
2040
|
+
compositeLayerEffects({ ...fx, backdrop: sub, content });
|
|
2041
|
+
if (this.linear) decodeInPlace(sub);
|
|
2042
|
+
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);
|
|
2043
|
+
return true;
|
|
2015
2044
|
}
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2045
|
+
applyClipped(clipped, buf, r) {
|
|
2046
|
+
let run = [];
|
|
2047
|
+
const flush = () => {
|
|
2048
|
+
if (run.length) this.applyFilterRun(run, buf, r);
|
|
2049
|
+
run = [];
|
|
2050
|
+
};
|
|
2051
|
+
for (const c of clipped) {
|
|
2052
|
+
if (this.isFilter(c)) {
|
|
2053
|
+
run.push(c);
|
|
2054
|
+
continue;
|
|
2055
|
+
}
|
|
2056
|
+
flush();
|
|
2057
|
+
const alone = this.renderedAlone(c);
|
|
2058
|
+
const coverage = alone ? null : this.base.maskCoverage(c, r, this.sources);
|
|
2059
|
+
let src;
|
|
2060
|
+
if (isGroup(c) && !alone) {
|
|
2061
|
+
src = new Float32Array(buf.length);
|
|
2062
|
+
if (this.runSteps(this.buildSteps(_nullishCoalesce(c.children, () => ( []))), src, true, r)) continue;
|
|
2063
|
+
} else src = this.content(c, r);
|
|
2064
|
+
if (!src) continue;
|
|
2065
|
+
const fill2 = !alone && this.isPixel(c) ? _nullishCoalesce(c.fillOpacity, () => ( 1)) : 1;
|
|
2066
|
+
const keep = new Float32Array(buf.length >> 2);
|
|
2067
|
+
for (let i = 3, p = 0; i < buf.length; i += 4, p++) keep[p] = buf[i];
|
|
2068
|
+
this.blend(buf, src, c.blend === "pass-through" ? "normal" : this.blendOf(c), c.opacity * fill2, coverage);
|
|
2069
|
+
for (let i = 3, p = 0; i < buf.length; i += 4, p++) buf[i] = keep[p];
|
|
2070
|
+
}
|
|
2071
|
+
flush();
|
|
2041
2072
|
}
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2073
|
+
applyFilterRun(layers, acc, r) {
|
|
2074
|
+
const visible = [];
|
|
2075
|
+
let masks;
|
|
2076
|
+
for (const node of layers) {
|
|
2077
|
+
if (!node.visible) continue;
|
|
2078
|
+
const cov = this.base.maskCoverage(node, r, this.sources);
|
|
2079
|
+
if (cov) {
|
|
2080
|
+
if (cov.every((v) => v <= 0)) continue;
|
|
2081
|
+
(masks ??= /* @__PURE__ */ new Map()).set(node.id, cov);
|
|
2082
|
+
}
|
|
2083
|
+
visible.push(node);
|
|
2084
|
+
}
|
|
2085
|
+
if (!visible.length) return;
|
|
2086
|
+
if (this.deep.applyFilterRunDeep) {
|
|
2087
|
+
if (this.linear) mapColour(acc, _chunk7ISPWEJAcjs.srgbEncode);
|
|
2088
|
+
this.deep.applyFilterRunDeep(visible, acc, r, masks, this.sources);
|
|
2089
|
+
if (this.linear) mapColour(acc, _chunk7ISPWEJAcjs.srgbDecode);
|
|
2090
|
+
return;
|
|
2091
|
+
}
|
|
2092
|
+
const bytes = this.to8(acc);
|
|
2093
|
+
_optionalChain([this, 'access', _8 => _8.profile, 'access', _9 => _9.applyFilterRun, 'optionalCall', _10 => _10(visible, bytes, r, masks, this.sources)]);
|
|
2094
|
+
acc.set(this.from8(bytes));
|
|
2095
|
+
}
|
|
2096
|
+
// --- Layer content ---------------------------------------------------------------
|
|
2097
|
+
/** Layers drawn by the 8-bit compositor alone (effects, pixel filters, content the editor draws). */
|
|
2098
|
+
/** A pixel(-like) layer with effects: composited in float through `compositeLayerEffects`. */
|
|
2099
|
+
deepEffects(layer) {
|
|
2100
|
+
return hasActiveEffects(layer.effects) && !this.isFilter(layer) && this.isPixel(layer) && !isGroup(layer);
|
|
2101
|
+
}
|
|
2102
|
+
renderedAlone(layer) {
|
|
2103
|
+
if (hasActiveEffects(layer.effects) && !this.isFilter(layer) && !this.deepEffects(layer)) return true;
|
|
2104
|
+
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)]);
|
|
2105
|
+
return !isGroup(layer);
|
|
2106
|
+
}
|
|
2107
|
+
blendOf(layer) {
|
|
2108
|
+
return _nullishCoalesce(_optionalChain([this, 'access', _17 => _17.profile, 'access', _18 => _18.contentBlend, 'optionalCall', _19 => _19(layer)]), () => ( layer.blend));
|
|
2109
|
+
}
|
|
2110
|
+
/** A layer's float RGBA over `r` (straight alpha, working space), or `null` when it has none there. */
|
|
2111
|
+
content(layer, r) {
|
|
2112
|
+
if (this.renderedAlone(layer)) {
|
|
2113
|
+
const solo = { ...layer, blend: isGroup(layer) && layer.blend === "pass-through" ? "pass-through" : "normal", opacity: 1, clipped: false };
|
|
2114
|
+
const bytes = this.base.composite([solo], r, this.sources);
|
|
2115
|
+
return this.from8(bytes);
|
|
2116
|
+
}
|
|
2117
|
+
const surface = this.sources.surfaceOf ? this.sources.surfaceOf(layer) : layer.surface;
|
|
2118
|
+
if (!surface) return null;
|
|
2119
|
+
const ox = _nullishCoalesce(_optionalChain([layer, 'access', _20 => _20.offset, 'optionalAccess', _21 => _21.x]), () => ( 0));
|
|
2120
|
+
const oy = _nullishCoalesce(_optionalChain([layer, 'access', _22 => _22.offset, 'optionalAccess', _23 => _23.y]), () => ( 0));
|
|
2121
|
+
const filters = this.isPixel(layer) ? _nullishCoalesce(_optionalChain([this, 'access', _24 => _24.deep, 'access', _25 => _25.pixelFiltersDeep, 'optionalCall', _26 => _26(layer)]), () => ( null)) : null;
|
|
2122
|
+
if (!filters) return this.samples(surface, { x: r.x - ox, y: r.y - oy, width: r.width, height: r.height });
|
|
2123
|
+
const m = filters.reach;
|
|
2124
|
+
const W = this.sources.width;
|
|
2125
|
+
const H = this.sources.height;
|
|
2126
|
+
const x0 = m ? Math.max(0, r.x - m) : r.x;
|
|
2127
|
+
const y0 = m ? Math.max(0, r.y - m) : r.y;
|
|
2128
|
+
const x1 = m ? Math.min(W, r.x + r.width + m) : r.x + r.width;
|
|
2129
|
+
const y1 = m ? Math.min(H, r.y + r.height + m) : r.y + r.height;
|
|
2130
|
+
if (x1 <= x0 || y1 <= y0) return new Float32Array(r.width * r.height * 4);
|
|
2131
|
+
const big = { x: x0, y: y0, width: x1 - x0, height: y1 - y0 };
|
|
2132
|
+
const data = this.samples(surface, { ...big, x: big.x - ox, y: big.y - oy });
|
|
2133
|
+
filters.apply(data, big.width, big.height, this.linear);
|
|
2134
|
+
if (big.x === r.x && big.y === r.y && big.width === r.width && big.height === r.height) return data;
|
|
2135
|
+
const out = new Float32Array(r.width * r.height * 4);
|
|
2136
|
+
for (let y = 0; y < r.height; y++) {
|
|
2137
|
+
const sy = r.y + y - big.y;
|
|
2138
|
+
if (sy < 0 || sy >= big.height) continue;
|
|
2139
|
+
for (let x = 0; x < r.width; x++) {
|
|
2140
|
+
const sx = r.x + x - big.x;
|
|
2141
|
+
if (sx < 0 || sx >= big.width) continue;
|
|
2142
|
+
const s = (sy * big.width + sx) * 4;
|
|
2143
|
+
const d = (y * r.width + x) * 4;
|
|
2144
|
+
out[d] = data[s];
|
|
2145
|
+
out[d + 1] = data[s + 1];
|
|
2146
|
+
out[d + 2] = data[s + 2];
|
|
2147
|
+
out[d + 3] = data[s + 3];
|
|
2148
|
+
}
|
|
2089
2149
|
}
|
|
2090
2150
|
return out;
|
|
2091
2151
|
}
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
const
|
|
2095
|
-
|
|
2096
|
-
const
|
|
2097
|
-
for (let i = 0; i <
|
|
2098
|
-
|
|
2099
|
-
|
|
2152
|
+
/** A surface's samples over `rect` (layer space) in the working space. */
|
|
2153
|
+
samples(surface, rect) {
|
|
2154
|
+
const samples = _chunk7ISPWEJAcjs.readDeepRegion.call(void 0, surface, rect, this.depth);
|
|
2155
|
+
if (samples instanceof Float32Array) return samples;
|
|
2156
|
+
const out = new Float32Array(samples.length);
|
|
2157
|
+
for (let i = 0; i < samples.length; i++) out[i] = samples[i] / 65535;
|
|
2158
|
+
return out;
|
|
2159
|
+
}
|
|
2160
|
+
/** 8-bit RGBA to the working space. */
|
|
2161
|
+
from8(bytes) {
|
|
2162
|
+
if (this.linear) return _chunk7ISPWEJAcjs.to32From8.call(void 0, bytes, 4);
|
|
2163
|
+
const out = new Float32Array(bytes.length);
|
|
2164
|
+
for (let i = 0; i < bytes.length; i++) out[i] = bytes[i] / 255;
|
|
2165
|
+
return out;
|
|
2166
|
+
}
|
|
2167
|
+
/** The working space to 8-bit RGBA. */
|
|
2168
|
+
to8(acc) {
|
|
2169
|
+
const out = new Uint8ClampedArray(acc.length);
|
|
2170
|
+
for (let i = 0; i < acc.length; i += 4) {
|
|
2171
|
+
for (let c = 0; c < 3; c++) out[i + c] = Math.round((this.linear ? _chunk7ISPWEJAcjs.srgbEncode.call(void 0, acc[i + c]) : acc[i + c]) * 255);
|
|
2172
|
+
out[i + 3] = Math.round(acc[i + 3] * 255);
|
|
2100
2173
|
}
|
|
2101
2174
|
return out;
|
|
2102
2175
|
}
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2176
|
+
// --- Blending --------------------------------------------------------------------
|
|
2177
|
+
/** `src` over `dst` with `mode` at `alpha` × coverage (straight alpha, float), as `blendTile`. */
|
|
2178
|
+
blend(dst, src, mode, alpha, coverage) {
|
|
2179
|
+
if (!(alpha > 0)) return;
|
|
2180
|
+
const normal = mode === "normal";
|
|
2181
|
+
const pigment = mode === "pigment";
|
|
2182
|
+
const cb = [0, 0, 0];
|
|
2183
|
+
const cs = [0, 0, 0];
|
|
2184
|
+
const mix = [0, 0, 0];
|
|
2185
|
+
for (let i = 0, p = 0; i < dst.length; i += 4, p++) {
|
|
2186
|
+
const sa = src[i + 3];
|
|
2187
|
+
if (!(sa > 0)) continue;
|
|
2188
|
+
const k = coverage ? alpha * coverage[p] : alpha;
|
|
2189
|
+
if (!(k > 0)) continue;
|
|
2190
|
+
const as = Math.min(1, sa * k);
|
|
2191
|
+
const ab = dst[i + 3];
|
|
2192
|
+
const ao = as + ab * (1 - as);
|
|
2193
|
+
if (ao <= 0) {
|
|
2194
|
+
dst[i] = dst[i + 1] = dst[i + 2] = dst[i + 3] = 0;
|
|
2195
|
+
continue;
|
|
2196
|
+
}
|
|
2197
|
+
if (normal && as >= 1) {
|
|
2198
|
+
dst[i] = src[i];
|
|
2199
|
+
dst[i + 1] = src[i + 1];
|
|
2200
|
+
dst[i + 2] = src[i + 2];
|
|
2201
|
+
dst[i + 3] = 1;
|
|
2202
|
+
continue;
|
|
2203
|
+
}
|
|
2204
|
+
for (let c = 0; c < 3; c++) {
|
|
2205
|
+
cb[c] = dst[i + c];
|
|
2206
|
+
cs[c] = src[i + c];
|
|
2207
|
+
}
|
|
2208
|
+
if (pigment) {
|
|
2209
|
+
if (this.linear) for (let c = 0; c < 3; c++) cb[c] = _chunk7ISPWEJAcjs.srgbEncode.call(void 0, cb[c]), cs[c] = _chunk7ISPWEJAcjs.srgbEncode.call(void 0, cs[c]);
|
|
2210
|
+
_chunk7ISPWEJAcjs.mixPigmentRgb.call(void 0, cb, cs, as / ao, mix);
|
|
2211
|
+
for (let c = 0; c < 3; c++) dst[i + c] = this.linear ? _chunk7ISPWEJAcjs.srgbDecode.call(void 0, mix[c]) : mix[c];
|
|
2212
|
+
dst[i + 3] = ao;
|
|
2213
|
+
continue;
|
|
2214
|
+
}
|
|
2215
|
+
const m = normal ? cs : _chunk7ISPWEJAcjs.blendRgb.call(void 0, mode, cb, cs);
|
|
2216
|
+
const wb = (1 - as) * ab;
|
|
2217
|
+
const ws = (1 - ab) * as;
|
|
2218
|
+
const wm = as * ab;
|
|
2219
|
+
for (let c = 0; c < 3; c++) dst[i + c] = (wb * cb[c] + ws * cs[c] + wm * m[c]) / ao;
|
|
2220
|
+
dst[i + 3] = ao;
|
|
2221
|
+
}
|
|
2222
|
+
}
|
|
2223
|
+
};
|
|
2224
|
+
function lerp(dst, before, alpha, coverage) {
|
|
2225
|
+
for (let i = 0, p = 0; i < dst.length; i += 4, p++) {
|
|
2226
|
+
const k = coverage ? alpha * coverage[p] : alpha;
|
|
2227
|
+
if (k >= 1) continue;
|
|
2228
|
+
for (let c = 0; c < 4; c++) dst[i + c] = before[i + c] + (dst[i + c] - before[i + c]) * k;
|
|
2111
2229
|
}
|
|
2112
|
-
return out;
|
|
2113
2230
|
}
|
|
2114
|
-
function
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
for (let i = 0; i < m.length; i++) strength[i] = Math.min(m[i] * gain, 1);
|
|
2121
|
-
paint(dst, strength, (i, c) => prepared.sample(1 - clamp012(m[i]), c), g.blend, g.opacity);
|
|
2231
|
+
function mapColour(data, f) {
|
|
2232
|
+
for (let i = 0; i < data.length; i += 4) {
|
|
2233
|
+
data[i] = f(data[i]);
|
|
2234
|
+
data[i + 1] = f(data[i + 1]);
|
|
2235
|
+
data[i + 2] = f(data[i + 2]);
|
|
2236
|
+
}
|
|
2122
2237
|
}
|
|
2123
|
-
function
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
const iy1 = Math.min(from.y + from.height, to.y + to.height);
|
|
2130
|
-
if (ix1 <= ix0 || iy1 <= iy0) return out;
|
|
2131
|
-
const n = ix1 - ix0;
|
|
2132
|
-
for (let y = iy0; y < iy1; y++) {
|
|
2133
|
-
const s = (y - from.y) * from.width + (ix0 - from.x);
|
|
2134
|
-
out.set(v.subarray(s, s + n), (y - to.y) * to.width + (ix0 - to.x));
|
|
2238
|
+
function workingToSamples(data, depth) {
|
|
2239
|
+
if (depth === 32) return data;
|
|
2240
|
+
const out = new Uint16Array(data.length);
|
|
2241
|
+
for (let i = 0; i < data.length; i++) {
|
|
2242
|
+
const v = data[i];
|
|
2243
|
+
out[i] = v > 0 ? v < 1 ? Math.round(v * 65535) : 65535 : 0;
|
|
2135
2244
|
}
|
|
2136
2245
|
return out;
|
|
2137
2246
|
}
|
|
2138
|
-
function
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
for (let i = 0; i < n; i++) shape[i] = content[i * 4 + 3] / 255;
|
|
2144
|
-
const before = new Float32Array(n * 4);
|
|
2145
|
-
for (let i = 0; i < n * 4; i++) before[i] = backdrop[i] / 255;
|
|
2146
|
-
const work = new Float32Array(before);
|
|
2147
|
-
const fx = (i, k) => crop(maps.per[i][k], maps.rect, rect, 0);
|
|
2148
|
-
const bounds = _nullishCoalesce(maps.bounds, () => ( rect));
|
|
2149
|
-
const env = { rect, bounds, canvas: input.canvas, anchor: { x: bounds.x, y: bounds.y }, ctx };
|
|
2150
|
-
const fill2 = clamp012(input.fillOpacity);
|
|
2151
|
-
const inside = (a) => a > INSIDE_EPS;
|
|
2152
|
-
const rev = [];
|
|
2153
|
-
for (let i = items.length - 1; i >= 0; i--) rev.push(i);
|
|
2154
|
-
const knockOut = (m, fillOpacity) => {
|
|
2155
|
-
const seeThrough = 1 - clamp012(fillOpacity);
|
|
2156
|
-
for (let i = 0; i < n; i++) m[i] *= 1 - shape[i] * seeThrough;
|
|
2157
|
-
};
|
|
2158
|
-
const normalLike = input.blend === "normal";
|
|
2159
|
-
for (const i of rev) {
|
|
2160
|
-
const e = items[i];
|
|
2161
|
-
if (e.kind !== "drop-shadow") continue;
|
|
2162
|
-
const m = fx(i, 0);
|
|
2163
|
-
if (e.knocksOut) knockOut(m, normalLike ? fill2 : 0);
|
|
2164
|
-
paintColor(work, m, e.color, e.blend, e.opacity);
|
|
2165
|
-
}
|
|
2166
|
-
for (const i of rev) {
|
|
2167
|
-
const e = items[i];
|
|
2168
|
-
if (e.kind !== "outer-glow") continue;
|
|
2169
|
-
const m = fx(i, 0);
|
|
2170
|
-
knockOut(m, fill2);
|
|
2171
|
-
paintGlow(work, m, e, env);
|
|
2172
|
-
}
|
|
2173
|
-
const lay = new Float32Array(n * 4);
|
|
2174
|
-
for (let i = 0; i < n; i++) {
|
|
2175
|
-
lay[i * 4] = content[i * 4] / 255;
|
|
2176
|
-
lay[i * 4 + 1] = content[i * 4 + 1] / 255;
|
|
2177
|
-
lay[i * 4 + 2] = content[i * 4 + 2] / 255;
|
|
2178
|
-
lay[i * 4 + 3] = inside(shape[i]) ? fill2 : 0;
|
|
2247
|
+
function encodeInPlace(d) {
|
|
2248
|
+
for (let i = 0; i < d.length; i += 4) {
|
|
2249
|
+
d[i] = _chunk7ISPWEJAcjs.srgbEncode.call(void 0, d[i]);
|
|
2250
|
+
d[i + 1] = _chunk7ISPWEJAcjs.srgbEncode.call(void 0, d[i + 1]);
|
|
2251
|
+
d[i + 2] = _chunk7ISPWEJAcjs.srgbEncode.call(void 0, d[i + 2]);
|
|
2179
2252
|
}
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
const sg = lay[p + 1];
|
|
2187
|
-
const sb = lay[p + 2];
|
|
2188
|
-
const sa = lay[p + 3];
|
|
2189
|
-
lay[p] = work[p];
|
|
2190
|
-
lay[p + 1] = work[p + 1];
|
|
2191
|
-
lay[p + 2] = work[p + 2];
|
|
2192
|
-
lay[p + 3] = work[p + 3];
|
|
2193
|
-
compositeAt(lay, p, input.blend, sep2, sr, sg, sb, sa);
|
|
2194
|
-
}
|
|
2195
|
-
}
|
|
2196
|
-
const rel = (m) => {
|
|
2197
|
-
for (let i = 0; i < n; i++) m[i] = inside(shape[i]) ? Math.min(m[i] / shape[i], 1) : 0;
|
|
2198
|
-
return m;
|
|
2199
|
-
};
|
|
2200
|
-
const full = new Float32Array(n);
|
|
2201
|
-
for (let i = 0; i < n; i++) full[i] = inside(shape[i]) ? 1 : 0;
|
|
2202
|
-
for (const i of rev) {
|
|
2203
|
-
const e = items[i];
|
|
2204
|
-
if (e.kind === "pattern-overlay") paintPattern(lay, full, e, env, e.blend, e.opacity);
|
|
2253
|
+
}
|
|
2254
|
+
function decodeInPlace(d) {
|
|
2255
|
+
for (let i = 0; i < d.length; i += 4) {
|
|
2256
|
+
d[i] = _chunk7ISPWEJAcjs.srgbDecode.call(void 0, d[i]);
|
|
2257
|
+
d[i + 1] = _chunk7ISPWEJAcjs.srgbDecode.call(void 0, d[i + 1]);
|
|
2258
|
+
d[i + 2] = _chunk7ISPWEJAcjs.srgbDecode.call(void 0, d[i + 2]);
|
|
2205
2259
|
}
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2260
|
+
}
|
|
2261
|
+
|
|
2262
|
+
// src/raster/blur.ts
|
|
2263
|
+
function gaussianKernel(sigma) {
|
|
2264
|
+
const r = Math.ceil(sigma * 3);
|
|
2265
|
+
const k = new Float32Array(2 * r + 1);
|
|
2266
|
+
let s = 0;
|
|
2267
|
+
for (let i = -r; i <= r; i++) {
|
|
2268
|
+
const v = Math.exp(-(i * i) / (2 * sigma * sigma));
|
|
2269
|
+
k[i + r] = v;
|
|
2270
|
+
s += v;
|
|
2209
2271
|
}
|
|
2210
|
-
for (
|
|
2211
|
-
|
|
2212
|
-
|
|
2272
|
+
for (let i = 0; i < k.length; i++) k[i] /= s;
|
|
2273
|
+
return k;
|
|
2274
|
+
}
|
|
2275
|
+
var DIRECT_GAUSSIAN_MAX_SIGMA = 8;
|
|
2276
|
+
function boxRadii(sigma) {
|
|
2277
|
+
const n = 3;
|
|
2278
|
+
const wIdeal = Math.sqrt(12 * sigma * sigma / n + 1);
|
|
2279
|
+
let wl = Math.floor(wIdeal);
|
|
2280
|
+
if (wl % 2 === 0) wl--;
|
|
2281
|
+
const wu = wl + 2;
|
|
2282
|
+
const mIdeal = (12 * sigma * sigma - n * wl * wl - 4 * n * wl - 3 * n) / (-4 * wl - 4);
|
|
2283
|
+
const m = Math.round(mIdeal);
|
|
2284
|
+
const sizes = [0, 1, 2].map((i) => i < m ? wl : wu);
|
|
2285
|
+
return sizes.map((s) => (s - 1) / 2);
|
|
2286
|
+
}
|
|
2287
|
+
function convolveLine(src, off, stride, len, k, edge, dst) {
|
|
2288
|
+
const r = (k.length - 1) / 2;
|
|
2289
|
+
for (let i = 0; i < len; i++) {
|
|
2290
|
+
let a = 0;
|
|
2291
|
+
const lo = i - r;
|
|
2292
|
+
for (let j = 0; j < k.length; j++) {
|
|
2293
|
+
let x = lo + j;
|
|
2294
|
+
if (x < 0 || x >= len) {
|
|
2295
|
+
if (edge === "zero") continue;
|
|
2296
|
+
x = x < 0 ? 0 : len - 1;
|
|
2297
|
+
}
|
|
2298
|
+
a += src[off + x * stride] * k[j];
|
|
2299
|
+
}
|
|
2300
|
+
dst[i] = a;
|
|
2213
2301
|
}
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2302
|
+
}
|
|
2303
|
+
function boxesLine(src, off, stride, len, radii, edge, a, b, dst) {
|
|
2304
|
+
const pad = radii.reduce((s, r) => s + r, 0);
|
|
2305
|
+
const plen = len + 2 * pad;
|
|
2306
|
+
for (let i = 0; i < plen; i++) {
|
|
2307
|
+
const j = i - pad;
|
|
2308
|
+
a[i] = j < 0 ? edge === "zero" ? 0 : src[off] : j >= len ? edge === "zero" ? 0 : src[off + (len - 1) * stride] : src[off + j * stride];
|
|
2217
2309
|
}
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2310
|
+
let from = a;
|
|
2311
|
+
let to = b;
|
|
2312
|
+
for (const r of radii) {
|
|
2313
|
+
let sum = 0;
|
|
2314
|
+
for (let i = 0; i <= Math.min(r, plen - 1); i++) sum += from[i];
|
|
2315
|
+
const k = 2 * r + 1;
|
|
2316
|
+
for (let i = 0; i < plen; i++) {
|
|
2317
|
+
to[i] = sum / k;
|
|
2318
|
+
const add = i + r + 1;
|
|
2319
|
+
const drop = i - r;
|
|
2320
|
+
if (add < plen) sum += from[add];
|
|
2321
|
+
if (drop >= 0) sum -= from[drop];
|
|
2322
|
+
}
|
|
2323
|
+
const t = from;
|
|
2324
|
+
from = to;
|
|
2325
|
+
to = t;
|
|
2221
2326
|
}
|
|
2222
|
-
for (
|
|
2223
|
-
|
|
2224
|
-
|
|
2327
|
+
for (let i = 0; i < len; i++) dst[i] = from[i + pad];
|
|
2328
|
+
}
|
|
2329
|
+
function gaussianBlur(src, w, h, sigma, edge = "zero") {
|
|
2330
|
+
const out = Float32Array.from(src);
|
|
2331
|
+
if (!(sigma >= 0.1) || w <= 0 || h <= 0) return out;
|
|
2332
|
+
const s = Math.min(sigma, 4 * Math.max(w, h));
|
|
2333
|
+
const line = new Float32Array(Math.max(w, h));
|
|
2334
|
+
const passes = [];
|
|
2335
|
+
if (s <= DIRECT_GAUSSIAN_MAX_SIGMA) {
|
|
2336
|
+
const k = gaussianKernel(s);
|
|
2337
|
+
passes.push((buf, off, stride, len) => convolveLine(buf, off, stride, len, k, edge, line));
|
|
2338
|
+
} else {
|
|
2339
|
+
const radii = boxRadii(s);
|
|
2340
|
+
const plen = Math.max(w, h) + 2 * radii.reduce((a2, r) => a2 + r, 0);
|
|
2341
|
+
const a = new Float32Array(plen);
|
|
2342
|
+
const b = new Float32Array(plen);
|
|
2343
|
+
passes.push((buf, off, stride, len) => boxesLine(buf, off, stride, len, radii, edge, a, b, line));
|
|
2225
2344
|
}
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
const [inW] = strokeWidths(st);
|
|
2232
|
-
if (!(inW > 0) || !din) continue;
|
|
2233
|
-
const m = new Float32Array(n);
|
|
2234
|
-
for (let i = 0; i < n; i++) m[i] = inside(shape[i]) ? clamp012(inW + 0.5 - din[i]) : 0;
|
|
2235
|
-
paintFill(lay, m, st.fill, frameOf(strokeIdx[k]), env, st.blend, st.opacity);
|
|
2345
|
+
for (const pass of passes) {
|
|
2346
|
+
for (let y = 0; y < h; y++) {
|
|
2347
|
+
pass(out, y * w, 1, w);
|
|
2348
|
+
out.set(line.subarray(0, w), y * w);
|
|
2349
|
+
}
|
|
2236
2350
|
}
|
|
2237
|
-
for (const
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
2351
|
+
for (const pass of passes) {
|
|
2352
|
+
for (let x = 0; x < w; x++) {
|
|
2353
|
+
pass(out, x, w, h);
|
|
2354
|
+
for (let y = 0; y < h; y++) out[y * w + x] = line[y];
|
|
2355
|
+
}
|
|
2242
2356
|
}
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
for (const
|
|
2252
|
-
|
|
2253
|
-
const
|
|
2254
|
-
|
|
2255
|
-
const share = new Float32Array(n);
|
|
2256
|
-
const ones = new Float32Array(n);
|
|
2257
|
-
for (let i = 0; i < n; i++) {
|
|
2258
|
-
const band = clamp012(outW + 0.5 - d[i]);
|
|
2259
|
-
let k;
|
|
2260
|
-
if (inside(shape[i])) {
|
|
2261
|
-
const c = clamp012(lay[i * 4 + 3]);
|
|
2262
|
-
k = c >= 1 ? 1 : clamp012((1 - clamp012(shape[i])) / (1 - c));
|
|
2263
|
-
} else k = band;
|
|
2264
|
-
share[i] = k * st.opacity * (1 - cover[i]);
|
|
2265
|
-
cover[i] += share[i];
|
|
2266
|
-
ones[i] = share[i] > 0 ? 1 : 0;
|
|
2267
|
-
}
|
|
2268
|
-
const blended = new Float32Array(base);
|
|
2269
|
-
paintFill(blended, ones, st.fill, frameOf(si), env, st.blend, 1);
|
|
2270
|
-
for (let i = 0; i < n; i++) {
|
|
2271
|
-
const s = share[i];
|
|
2272
|
-
if (!(s > 0)) continue;
|
|
2273
|
-
const p = i * 4;
|
|
2274
|
-
const ba = blended[p + 3];
|
|
2275
|
-
acc[p] += s * blended[p] * ba;
|
|
2276
|
-
acc[p + 1] += s * blended[p + 1] * ba;
|
|
2277
|
-
acc[p + 2] += s * blended[p + 2] * ba;
|
|
2278
|
-
acc[p + 3] += s * ba;
|
|
2279
|
-
}
|
|
2357
|
+
return out;
|
|
2358
|
+
}
|
|
2359
|
+
|
|
2360
|
+
// src/raster/layers.ts
|
|
2361
|
+
var childrenOf = (l) => l.type === "group" ? _nullishCoalesce(l.children, () => ( null)) : null;
|
|
2362
|
+
function flattenLayers(layers) {
|
|
2363
|
+
const out = [];
|
|
2364
|
+
const walk = (list) => {
|
|
2365
|
+
for (const l of list) {
|
|
2366
|
+
out.push(l);
|
|
2367
|
+
const c = childrenOf(l);
|
|
2368
|
+
if (c) walk(c);
|
|
2280
2369
|
}
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2370
|
+
};
|
|
2371
|
+
walk(layers);
|
|
2372
|
+
return out;
|
|
2373
|
+
}
|
|
2374
|
+
function findLayer(layers, id) {
|
|
2375
|
+
const walk = (list, parent, path) => {
|
|
2376
|
+
for (let i = 0; i < list.length; i++) {
|
|
2377
|
+
const l = list[i];
|
|
2378
|
+
if (l.id === id) return { layer: l, parent, index: i, path };
|
|
2379
|
+
const c = childrenOf(l);
|
|
2380
|
+
if (c) {
|
|
2381
|
+
const g = l;
|
|
2382
|
+
const hit = walk(c, g, [...path, g]);
|
|
2383
|
+
if (hit) return hit;
|
|
2292
2384
|
}
|
|
2293
2385
|
}
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
if (alpha <= 0) {
|
|
2320
|
-
backdrop[p] = backdrop[p + 1] = backdrop[p + 2] = backdrop[p + 3] = 0;
|
|
2321
|
-
continue;
|
|
2386
|
+
return null;
|
|
2387
|
+
};
|
|
2388
|
+
return walk(layers, null, []);
|
|
2389
|
+
}
|
|
2390
|
+
function mapLayer(layers, id, fn) {
|
|
2391
|
+
let changed = false;
|
|
2392
|
+
const walk = (list) => {
|
|
2393
|
+
let out = null;
|
|
2394
|
+
for (let i = 0; i < list.length; i++) {
|
|
2395
|
+
const l = list[i];
|
|
2396
|
+
let next = l;
|
|
2397
|
+
if (l.id === id) {
|
|
2398
|
+
next = fn(l);
|
|
2399
|
+
changed = true;
|
|
2400
|
+
} else {
|
|
2401
|
+
const c = childrenOf(l);
|
|
2402
|
+
if (c) {
|
|
2403
|
+
const children = walk(c);
|
|
2404
|
+
if (children !== c) next = { ...l, children };
|
|
2405
|
+
}
|
|
2406
|
+
}
|
|
2407
|
+
if (next !== l) {
|
|
2408
|
+
if (!out) out = list.slice(0, i);
|
|
2409
|
+
if (next) out.push(next);
|
|
2410
|
+
} else if (out) out.push(l);
|
|
2322
2411
|
}
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2412
|
+
return _nullishCoalesce(out, () => ( list));
|
|
2413
|
+
};
|
|
2414
|
+
const result = walk(layers);
|
|
2415
|
+
return changed ? result : layers;
|
|
2326
2416
|
}
|
|
2327
|
-
function
|
|
2328
|
-
const
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
blend: layer.blend,
|
|
2339
|
-
opacity: layer.opacity,
|
|
2340
|
-
fillOpacity: _nullishCoalesce(layer.fillOpacity, () => ( 1)),
|
|
2341
|
-
canvas,
|
|
2342
|
-
ctx
|
|
2417
|
+
function insertLayer(layers, layer, parentId, index) {
|
|
2418
|
+
const put = (list) => {
|
|
2419
|
+
const at = index === void 0 ? list.length : Math.max(0, Math.min(list.length, index));
|
|
2420
|
+
const next = list.slice();
|
|
2421
|
+
next.splice(at, 0, layer);
|
|
2422
|
+
return next;
|
|
2423
|
+
};
|
|
2424
|
+
if (!parentId) return put(layers);
|
|
2425
|
+
return mapLayer(layers, parentId, (g) => {
|
|
2426
|
+
const c = childrenOf(g);
|
|
2427
|
+
return c ? { ...g, children: put(c) } : g;
|
|
2343
2428
|
});
|
|
2344
2429
|
}
|
|
2430
|
+
function isLayerLocked(layer, what) {
|
|
2431
|
+
return Boolean(_optionalChain([layer, 'access', _27 => _27.locks, 'optionalAccess', _28 => _28.all]) || _optionalChain([layer, 'access', _29 => _29.locks, 'optionalAccess', _30 => _30[what]]));
|
|
2432
|
+
}
|
|
2345
2433
|
|
|
2346
2434
|
// src/raster/compositor.ts
|
|
2347
2435
|
var TILE_PIXELS = _chunk7ISPWEJAcjs.TILE * _chunk7ISPWEJAcjs.TILE;
|
|
@@ -2563,7 +2651,7 @@ var RasterCompositor = (_class = class {
|
|
|
2563
2651
|
const dirty = grow > 0 ? options.dirty.map((d) => inflateRect(d, grow)) : options.dirty;
|
|
2564
2652
|
for (const { tx, ty } of _chunk7ISPWEJAcjs.tilesInRect.call(void 0, rect)) {
|
|
2565
2653
|
stats.tiles++;
|
|
2566
|
-
const before = _optionalChain([this, 'access',
|
|
2654
|
+
const before = _optionalChain([this, 'access', _31 => _31.tiles, 'access', _32 => _32.get, 'call', _33 => _33(_chunk7ISPWEJAcjs.tileKey.call(void 0, tx, ty)), 'optionalAccess', _34 => _34.result]);
|
|
2567
2655
|
const data = this.compositeTile(layers, steps, tx, ty, stats, dirty ? dirtyInTile(dirty, tx, ty) : null);
|
|
2568
2656
|
onTile(tx, ty, data, data !== before);
|
|
2569
2657
|
}
|
|
@@ -2591,13 +2679,33 @@ var RasterCompositor = (_class = class {
|
|
|
2591
2679
|
this.setSources(sources);
|
|
2592
2680
|
return this.maskTile(layer, r);
|
|
2593
2681
|
}
|
|
2682
|
+
/**
|
|
2683
|
+
* For the float compositor: everything `compositeLayerEffects` needs for `layer` over `r` but
|
|
2684
|
+
* the pixels (the area its effects reach inside `r`, the effect maps built from its 8-bit
|
|
2685
|
+
* shape, blend, opacities, canvas and context), or `null` when nothing reaches `r`.
|
|
2686
|
+
*/
|
|
2687
|
+
effectsInput(layer, r, sources) {
|
|
2688
|
+
this.setSources(sources);
|
|
2689
|
+
const maps = this.effectMapsOf(layer);
|
|
2690
|
+
const rect = this.effectArea(layer, maps, r);
|
|
2691
|
+
if (!rect) return null;
|
|
2692
|
+
return {
|
|
2693
|
+
rect,
|
|
2694
|
+
maps,
|
|
2695
|
+
blend: isGroup2(layer) ? layer.blend === "pass-through" ? "normal" : layer.blend : this.contentBlend(layer),
|
|
2696
|
+
opacity: layer.opacity,
|
|
2697
|
+
fillOpacity: this.isPixel(layer) ? _nullishCoalesce(layer.fillOpacity, () => ( 1)) : 1,
|
|
2698
|
+
canvas: { x: 0, y: 0, width: this.sources.width, height: this.sources.height },
|
|
2699
|
+
ctx: this.effectContext()
|
|
2700
|
+
};
|
|
2701
|
+
}
|
|
2594
2702
|
// --- Steps -------------------------------------------------------------------
|
|
2595
2703
|
/** Pixel layers, and the layer kinds the profile composites like them. */
|
|
2596
2704
|
isPixel(l) {
|
|
2597
|
-
return l.type === "pixel" || (_nullishCoalesce(_optionalChain([this, 'access',
|
|
2705
|
+
return l.type === "pixel" || (_nullishCoalesce(_optionalChain([this, 'access', _35 => _35.profile, 'access', _36 => _36.isPixelLike, 'optionalCall', _37 => _37(l)]), () => ( false)));
|
|
2598
2706
|
}
|
|
2599
2707
|
isFilter(l) {
|
|
2600
|
-
return _nullishCoalesce(_optionalChain([this, 'access',
|
|
2708
|
+
return _nullishCoalesce(_optionalChain([this, 'access', _38 => _38.profile, 'access', _39 => _39.isFilterLayer, 'optionalCall', _40 => _40(l)]), () => ( false));
|
|
2601
2709
|
}
|
|
2602
2710
|
/**
|
|
2603
2711
|
* Groups a layer list into compositing steps: clipped layers join the nearest unclipped
|
|
@@ -2636,9 +2744,9 @@ var RasterCompositor = (_class = class {
|
|
|
2636
2744
|
if (key !== void 0) return key;
|
|
2637
2745
|
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;
|
|
2638
2746
|
const base = [layer.type, layer.id, layer.visible, layer.opacity, layer.blend, Boolean(layer.clipped), mask];
|
|
2639
|
-
if (this.isPixel(layer)) base.push(_nullishCoalesce(_optionalChain([layer, 'access',
|
|
2747
|
+
if (this.isPixel(layer)) base.push(_nullishCoalesce(_optionalChain([layer, 'access', _41 => _41.offset, 'optionalAccess', _42 => _42.x]), () => ( 0)), _nullishCoalesce(_optionalChain([layer, 'access', _43 => _43.offset, 'optionalAccess', _44 => _44.y]), () => ( 0)), _nullishCoalesce(layer.fillOpacity, () => ( 1)));
|
|
2640
2748
|
if (this.hasEffects(layer)) base.push(effectsFingerprint(layer.effects));
|
|
2641
|
-
const extra = _optionalChain([this, 'access',
|
|
2749
|
+
const extra = _optionalChain([this, 'access', _45 => _45.profile, 'access', _46 => _46.layerKey, 'optionalCall', _47 => _47(layer)]);
|
|
2642
2750
|
if (extra !== void 0) base.push(extra);
|
|
2643
2751
|
key = JSON.stringify(base);
|
|
2644
2752
|
this.propsKeyCache.set(layer, key);
|
|
@@ -2805,7 +2913,7 @@ var RasterCompositor = (_class = class {
|
|
|
2805
2913
|
const refs = [surface.defaultValue];
|
|
2806
2914
|
const r = { x: tx * _chunk7ISPWEJAcjs.TILE - dx, y: ty * _chunk7ISPWEJAcjs.TILE - dy, width: _chunk7ISPWEJAcjs.TILE, height: _chunk7ISPWEJAcjs.TILE };
|
|
2807
2915
|
for (const t of _chunk7ISPWEJAcjs.tilesInRect.call(void 0, r)) refs.push(_nullishCoalesce(surface.getTile(t.tx, t.ty), () => ( null)));
|
|
2808
|
-
refs.push(...this.maskRefs(layer, tx, ty, _nullishCoalesce(_optionalChain([layer, 'access',
|
|
2916
|
+
refs.push(...this.maskRefs(layer, tx, ty, _nullishCoalesce(_optionalChain([layer, 'access', _48 => _48.offset, 'optionalAccess', _49 => _49.x]), () => ( 0)), _nullishCoalesce(_optionalChain([layer, 'access', _50 => _50.offset, 'optionalAccess', _51 => _51.y]), () => ( 0))));
|
|
2809
2917
|
return { key, refs };
|
|
2810
2918
|
}
|
|
2811
2919
|
// --- Layer effects ------------------------------------------------------------
|
|
@@ -2835,7 +2943,7 @@ var RasterCompositor = (_class = class {
|
|
|
2835
2943
|
this.fxContext = {
|
|
2836
2944
|
light: _nullishCoalesce(sources.globalLight, () => ( DEFAULT_GLOBAL_LIGHT)),
|
|
2837
2945
|
pattern: (id) => {
|
|
2838
|
-
const p = _nullishCoalesce(_optionalChain([sources, 'access',
|
|
2946
|
+
const p = _nullishCoalesce(_optionalChain([sources, 'access', _52 => _52.pattern, 'optionalCall', _53 => _53(id)]), () => ( builtinPattern(id)));
|
|
2839
2947
|
if (!p || !(p.width > 0 && p.height > 0) || p.data.length < p.width * p.height * 4) return null;
|
|
2840
2948
|
let t = tiles.get(p);
|
|
2841
2949
|
if (!t) {
|
|
@@ -2963,7 +3071,7 @@ var RasterCompositor = (_class = class {
|
|
|
2963
3071
|
* without filters or a feathered or parametric mask (those spread a change beyond it).
|
|
2964
3072
|
*/
|
|
2965
3073
|
dirtyCoversShape(layer) {
|
|
2966
|
-
if (!this.isPixel(layer) || _optionalChain([this, 'access',
|
|
3074
|
+
if (!this.isPixel(layer) || _optionalChain([this, 'access', _54 => _54.profile, 'access', _55 => _55.pixelFilters, 'optionalCall', _56 => _56(layer)])) return false;
|
|
2967
3075
|
const mask = layer.mask;
|
|
2968
3076
|
return !mask || mask.enabled === false || !mask.source && !((_nullishCoalesce(mask.feather, () => ( 0))) > 0);
|
|
2969
3077
|
}
|
|
@@ -3051,10 +3159,10 @@ var RasterCompositor = (_class = class {
|
|
|
3051
3159
|
*/
|
|
3052
3160
|
layerPixels(layer) {
|
|
3053
3161
|
const raw = this.sources.surfaceOf ? this.sources.surfaceOf(layer) : layer.surface;
|
|
3054
|
-
const ox = _nullishCoalesce(_optionalChain([layer, 'access',
|
|
3055
|
-
const oy = _nullishCoalesce(_optionalChain([layer, 'access',
|
|
3056
|
-
const filters = _nullishCoalesce(_optionalChain([this, 'access',
|
|
3057
|
-
if (!_optionalChain([filters, 'optionalAccess',
|
|
3162
|
+
const ox = _nullishCoalesce(_optionalChain([layer, 'access', _57 => _57.offset, 'optionalAccess', _58 => _58.x]), () => ( 0));
|
|
3163
|
+
const oy = _nullishCoalesce(_optionalChain([layer, 'access', _59 => _59.offset, 'optionalAccess', _60 => _60.y]), () => ( 0));
|
|
3164
|
+
const filters = _nullishCoalesce(_optionalChain([this, 'access', _61 => _61.profile, 'access', _62 => _62.pixelFilters, 'optionalCall', _63 => _63(layer)]), () => ( null));
|
|
3165
|
+
if (!_optionalChain([filters, 'optionalAccess', _64 => _64.spatial])) return { surface: raw, dx: ox, dy: oy, perPixel: filters };
|
|
3058
3166
|
const fkey = `${ox},${oy}:${filters.key}`;
|
|
3059
3167
|
let byKey = this.filteredCache.get(raw);
|
|
3060
3168
|
if (!byKey) {
|
|
@@ -3071,7 +3179,7 @@ var RasterCompositor = (_class = class {
|
|
|
3071
3179
|
}
|
|
3072
3180
|
/** RGBA of a content layer over `r` (document space, inside one tile), or `null` when it has nothing there. */
|
|
3073
3181
|
contentTile(layer, r) {
|
|
3074
|
-
if (!this.isPixel(layer)) return _nullishCoalesce(_optionalChain([this, 'access',
|
|
3182
|
+
if (!this.isPixel(layer)) return _nullishCoalesce(_optionalChain([this, 'access', _65 => _65.profile, 'access', _66 => _66.contentTile, 'optionalCall', _67 => _67(layer, r, this.sources)]), () => ( null));
|
|
3075
3183
|
const { surface, dx, dy, perPixel } = this.layerPixels(layer);
|
|
3076
3184
|
const src = { x: r.x - dx, y: r.y - dy, width: r.width, height: r.height };
|
|
3077
3185
|
const covered = _chunk7ISPWEJAcjs.tilesInRect.call(void 0, src).map((t) => surface.getTile(t.tx, t.ty));
|
|
@@ -3086,7 +3194,7 @@ var RasterCompositor = (_class = class {
|
|
|
3086
3194
|
let byKey = this.contentCache.get(anchor);
|
|
3087
3195
|
const refsKey = `${r.x},${r.y}:${fkey}`;
|
|
3088
3196
|
if (aligned) {
|
|
3089
|
-
const hit = _optionalChain([byKey, 'optionalAccess',
|
|
3197
|
+
const hit = _optionalChain([byKey, 'optionalAccess', _68 => _68.get, 'call', _69 => _69(refsKey)]);
|
|
3090
3198
|
if (hit) return hit;
|
|
3091
3199
|
}
|
|
3092
3200
|
const data = _chunk7ISPWEJAcjs.readRegion.call(void 0, surface, src);
|
|
@@ -3124,7 +3232,7 @@ var RasterCompositor = (_class = class {
|
|
|
3124
3232
|
const H = this.sources.height;
|
|
3125
3233
|
let v = new Float32Array(W * H);
|
|
3126
3234
|
if (mask.source) {
|
|
3127
|
-
const generated = _nullishCoalesce(_optionalChain([this, 'access',
|
|
3235
|
+
const generated = _nullishCoalesce(_optionalChain([this, 'access', _70 => _70.profile, 'access', _71 => _71.maskSourcePlane, 'optionalCall', _72 => _72(mask.source, W, H, this.sources)]), () => ( null));
|
|
3128
3236
|
if (!generated || generated.length !== W * H) v.fill(1);
|
|
3129
3237
|
else v.set(generated);
|
|
3130
3238
|
} else {
|
|
@@ -3143,8 +3251,8 @@ var RasterCompositor = (_class = class {
|
|
|
3143
3251
|
maskTile(layer, r) {
|
|
3144
3252
|
const mask = layer.mask;
|
|
3145
3253
|
if (!mask || mask.enabled === false) return null;
|
|
3146
|
-
const ox = this.isPixel(layer) ? _nullishCoalesce(_optionalChain([layer, 'access',
|
|
3147
|
-
const oy = this.isPixel(layer) ? _nullishCoalesce(_optionalChain([layer, 'access',
|
|
3254
|
+
const ox = this.isPixel(layer) ? _nullishCoalesce(_optionalChain([layer, 'access', _73 => _73.offset, 'optionalAccess', _74 => _74.x]), () => ( 0)) : 0;
|
|
3255
|
+
const oy = this.isPixel(layer) ? _nullishCoalesce(_optionalChain([layer, 'access', _75 => _75.offset, 'optionalAccess', _76 => _76.y]), () => ( 0)) : 0;
|
|
3148
3256
|
const n = r.width * r.height;
|
|
3149
3257
|
const out = new Float32Array(n);
|
|
3150
3258
|
const density = _nullishCoalesce(mask.density, () => ( 1));
|
|
@@ -3228,7 +3336,7 @@ var RasterCompositor = (_class = class {
|
|
|
3228
3336
|
return empty;
|
|
3229
3337
|
}
|
|
3230
3338
|
contentBlend(layer) {
|
|
3231
|
-
return _nullishCoalesce(_optionalChain([this, 'access',
|
|
3339
|
+
return _nullishCoalesce(_optionalChain([this, 'access', _77 => _77.profile, 'access', _78 => _78.contentBlend, 'optionalCall', _79 => _79(layer)]), () => ( layer.blend));
|
|
3232
3340
|
}
|
|
3233
3341
|
blendOnto(acc, src, empty, mode, alpha, coverage) {
|
|
3234
3342
|
if (!(alpha > 0)) return empty;
|
|
@@ -3282,7 +3390,7 @@ var RasterCompositor = (_class = class {
|
|
|
3282
3390
|
}
|
|
3283
3391
|
visible.push(node);
|
|
3284
3392
|
}
|
|
3285
|
-
if (visible.length) _optionalChain([this, 'access',
|
|
3393
|
+
if (visible.length) _optionalChain([this, 'access', _80 => _80.profile, 'access', _81 => _81.applyFilterRun, 'optionalCall', _82 => _82(visible, acc, r, masks, this.sources)]);
|
|
3286
3394
|
}
|
|
3287
3395
|
}, _class);
|
|
3288
3396
|
function filterOverCanvas(surface, ox, oy, filters, width, height) {
|
|
@@ -3646,10 +3754,10 @@ function assemble(src, tiles) {
|
|
|
3646
3754
|
return new (0, _chunk7ISPWEJAcjs.TiledSurface)(src.channels, tiles, src.defaultValue);
|
|
3647
3755
|
}
|
|
3648
3756
|
function transformedBounds(source, h) {
|
|
3649
|
-
if (!(source.width > 0 && source.height > 0) || !
|
|
3650
|
-
const pts =
|
|
3757
|
+
if (!(source.width > 0 && source.height > 0) || !_chunkMUUXNRU4cjs.invertHomography.call(void 0, h)) return null;
|
|
3758
|
+
const pts = _chunkMUUXNRU4cjs.boxQuad.call(void 0, source).map((p) => _chunkMUUXNRU4cjs.applyHomography.call(void 0, h, p));
|
|
3651
3759
|
if (pts.some((p) => !p)) return null;
|
|
3652
|
-
return
|
|
3760
|
+
return _chunkMUUXNRU4cjs.cornerBounds.call(void 0, pts);
|
|
3653
3761
|
}
|
|
3654
3762
|
function transformSurface(src, h, options = {}) {
|
|
3655
3763
|
const interp = _nullishCoalesce(options.interpolation, () => ( "bicubic"));
|
|
@@ -3659,10 +3767,10 @@ function transformSurface(src, h, options = {}) {
|
|
|
3659
3767
|
const given = options.source;
|
|
3660
3768
|
const step = normalizeStep(options.step);
|
|
3661
3769
|
const depth = resampleDepth(src, step);
|
|
3662
|
-
if (
|
|
3770
|
+
if (_chunkMUUXNRU4cjs.isIdentityHomography.call(void 0, h, 1e-12) && !given && !options.clip) return src;
|
|
3663
3771
|
const dx = h[2] / h[8];
|
|
3664
3772
|
const dy = h[5] / h[8];
|
|
3665
|
-
if (!given && !options.clip &&
|
|
3773
|
+
if (!given && !options.clip && _chunkMUUXNRU4cjs.isIdentityHomography.call(void 0, [h[0], h[1], 0, h[3], h[4], 0, h[6], h[7], h[8]], 1e-12) && Math.abs(dx - Math.round(dx)) < 1e-9 && Math.abs(dy - Math.round(dy)) < 1e-9) {
|
|
3666
3774
|
const mx = Math.round(dx);
|
|
3667
3775
|
const my = Math.round(dy);
|
|
3668
3776
|
const b = src.bounds;
|
|
@@ -3676,8 +3784,8 @@ function transformSurface(src, h, options = {}) {
|
|
|
3676
3784
|
let H = h;
|
|
3677
3785
|
let S = src;
|
|
3678
3786
|
if (interp === "bicubic") {
|
|
3679
|
-
const inv0 =
|
|
3680
|
-
const c =
|
|
3787
|
+
const inv0 = _chunkMUUXNRU4cjs.invertHomography.call(void 0, H);
|
|
3788
|
+
const c = _chunkMUUXNRU4cjs.applyHomography.call(void 0, H, { x: srcRect.x + srcRect.width / 2, y: srcRect.y + srcRect.height / 2 });
|
|
3681
3789
|
if (inv0 && c) {
|
|
3682
3790
|
const [su, sv] = inverseStretch(inv0, c.x, c.y);
|
|
3683
3791
|
const kx = reduction(su);
|
|
@@ -3686,11 +3794,11 @@ function transformSurface(src, h, options = {}) {
|
|
|
3686
3794
|
const red = boxReduce(src, srcRect, kx, ky, depth);
|
|
3687
3795
|
S = red.surface;
|
|
3688
3796
|
srcRect = red.rect;
|
|
3689
|
-
H =
|
|
3797
|
+
H = _chunkMUUXNRU4cjs.multiplyHomographies.call(void 0, [kx, 0, 0, 0, ky, 0, 0, 0, 1], H);
|
|
3690
3798
|
}
|
|
3691
3799
|
}
|
|
3692
3800
|
}
|
|
3693
|
-
const inv =
|
|
3801
|
+
const inv = _chunkMUUXNRU4cjs.invertHomography.call(void 0, H);
|
|
3694
3802
|
if (!inv) return empty;
|
|
3695
3803
|
const sr = srcRect;
|
|
3696
3804
|
const fwd = [
|
|
@@ -3698,12 +3806,12 @@ function transformSurface(src, h, options = {}) {
|
|
|
3698
3806
|
{ x: sr.x + sr.width + 1, y: sr.y - 1 },
|
|
3699
3807
|
{ x: sr.x + sr.width + 1, y: sr.y + sr.height + 1 },
|
|
3700
3808
|
{ x: sr.x - 1, y: sr.y + sr.height + 1 }
|
|
3701
|
-
].map((p) =>
|
|
3809
|
+
].map((p) => _chunkMUUXNRU4cjs.homographyW.call(void 0, H, p));
|
|
3702
3810
|
const side = fwd.every((w) => w > 0) ? 1 : fwd.every((w) => w < 0) ? -1 : 0;
|
|
3703
3811
|
const wLo = 1 / fwd.reduce((m, w) => Math.max(m, Math.abs(w)), 0);
|
|
3704
|
-
const front = side === 0 ?
|
|
3705
|
-
const corners =
|
|
3706
|
-
const bounds = corners.every(Boolean) ?
|
|
3812
|
+
const front = side === 0 ? _chunkMUUXNRU4cjs.homographyFrontSide.call(void 0, H, sr) : 0;
|
|
3813
|
+
const corners = _chunkMUUXNRU4cjs.boxQuad.call(void 0, sr).map((p) => _chunkMUUXNRU4cjs.applyHomography.call(void 0, H, p));
|
|
3814
|
+
const bounds = corners.every(Boolean) ? _chunkMUUXNRU4cjs.cornerBounds.call(void 0, corners) : null;
|
|
3707
3815
|
let dst;
|
|
3708
3816
|
if (options.clip && bounds && side !== 0) dst = intersect(bounds, options.clip);
|
|
3709
3817
|
else dst = _nullishCoalesce(options.clip, () => ( bounds));
|
|
@@ -3730,7 +3838,7 @@ function transformSurface(src, h, options = {}) {
|
|
|
3730
3838
|
{ x: t.x + t.width, y: t.y + t.height },
|
|
3731
3839
|
{ x: t.x, y: t.y + t.height }
|
|
3732
3840
|
];
|
|
3733
|
-
const wc = tc.map((p) =>
|
|
3841
|
+
const wc = tc.map((p) => _chunkMUUXNRU4cjs.homographyW.call(void 0, inv, p));
|
|
3734
3842
|
let poly = tc;
|
|
3735
3843
|
if (side !== 0) {
|
|
3736
3844
|
const dd = wc.map((w) => side * w - wLo);
|
|
@@ -3752,7 +3860,7 @@ function transformSurface(src, h, options = {}) {
|
|
|
3752
3860
|
let foot;
|
|
3753
3861
|
if (straddles) foot = sr;
|
|
3754
3862
|
else {
|
|
3755
|
-
const fp = poly.map((p) =>
|
|
3863
|
+
const fp = poly.map((p) => _chunkMUUXNRU4cjs.applyHomography.call(void 0, inv, p));
|
|
3756
3864
|
if (fp.some((p) => !p)) foot = sr;
|
|
3757
3865
|
else {
|
|
3758
3866
|
const xs = fp.map((p) => p.x);
|
|
@@ -4201,5 +4309,5 @@ function compositeSurfaceOver(base, top) {
|
|
|
4201
4309
|
|
|
4202
4310
|
|
|
4203
4311
|
|
|
4204
|
-
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.
|
|
4205
|
-
//# sourceMappingURL=chunk-
|
|
4312
|
+
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.CURVE_LUT_SIZE = CURVE_LUT_SIZE; exports.curveLut = curveLut; exports.PatternTile = PatternTile; exports.PatternPlacement = PatternPlacement; exports.builtinPatternIds = builtinPatternIds; exports.builtinPattern = builtinPattern; exports.hashNoise = hashNoise; 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.DeepCompositor = DeepCompositor; exports.workingToSamples = workingToSamples; exports.DIRECT_GAUSSIAN_MAX_SIGMA = DIRECT_GAUSSIAN_MAX_SIGMA; exports.gaussianBlur = gaussianBlur; exports.flattenLayers = flattenLayers; exports.findLayer = findLayer; exports.mapLayer = mapLayer; exports.insertLayer = insertLayer; exports.isLayerLocked = isLayerLocked; exports.blendTile = blendTile; exports.RasterCompositor = RasterCompositor; exports.changedTiles = changedTiles; 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;
|
|
4313
|
+
//# sourceMappingURL=chunk-DFFBJV3U.cjs.map
|