@pixerate/editor 0.113.0 → 0.115.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 +8 -0
- package/dist/animation-editor/index.cjs +60 -54
- package/dist/animation-editor/index.cjs.map +1 -1
- package/dist/animation-editor/index.d.cts +3 -3
- package/dist/animation-editor/index.d.ts +3 -3
- package/dist/animation-editor/index.js +14 -8
- package/dist/animation-editor/index.js.map +1 -1
- package/dist/builtin-CY97ppKM.d.cts +354 -0
- package/dist/builtin-CY97ppKM.d.ts +354 -0
- package/dist/canvas/index.cjs +3 -3
- package/dist/canvas/index.cjs.map +1 -1
- package/dist/canvas/index.js +9 -9
- package/dist/chunk-26PGXHY7.cjs +753 -0
- package/dist/chunk-26PGXHY7.cjs.map +1 -0
- package/dist/chunk-2OJACTPR.cjs +929 -0
- package/dist/chunk-2OJACTPR.cjs.map +1 -0
- package/dist/chunk-3UFGNHSP.js +929 -0
- package/dist/chunk-3UFGNHSP.js.map +1 -0
- package/dist/chunk-643B2HKC.cjs +534 -0
- package/dist/chunk-643B2HKC.cjs.map +1 -0
- package/dist/chunk-6FCKOS2B.js +534 -0
- package/dist/chunk-6FCKOS2B.js.map +1 -0
- package/dist/chunk-BRLYOPLT.js +2574 -0
- package/dist/chunk-BRLYOPLT.js.map +1 -0
- package/dist/{chunk-LQEEDHOP.js → chunk-C6C5PDKU.js} +759 -761
- package/dist/chunk-C6C5PDKU.js.map +1 -0
- package/dist/{chunk-4KLT7ZYS.cjs → chunk-DFQEX3AM.cjs} +29 -29
- package/dist/{chunk-4KLT7ZYS.cjs.map → chunk-DFQEX3AM.cjs.map} +1 -1
- package/dist/chunk-G5NMLUVF.cjs +2574 -0
- package/dist/chunk-G5NMLUVF.cjs.map +1 -0
- package/dist/{chunk-YGIMK4NX.cjs → chunk-I7FQBWMQ.cjs} +813 -842
- package/dist/chunk-I7FQBWMQ.cjs.map +1 -0
- package/dist/{chunk-LPYOIVLA.js → chunk-LKCYANMW.js} +3 -3
- package/dist/{chunk-W3GXSUSQ.cjs → chunk-LPLCWZTM.cjs} +5087 -1283
- package/dist/chunk-LPLCWZTM.cjs.map +1 -0
- package/dist/chunk-MMVHBKMM.js +753 -0
- package/dist/chunk-MMVHBKMM.js.map +1 -0
- package/dist/{chunk-POGBUYWE.cjs → chunk-ST7E3NEE.cjs} +857 -859
- package/dist/chunk-ST7E3NEE.cjs.map +1 -0
- package/dist/{chunk-7VOHOPLW.cjs → chunk-TCKIXI46.cjs} +59 -59
- package/dist/{chunk-7VOHOPLW.cjs.map → chunk-TCKIXI46.cjs.map} +1 -1
- package/dist/{chunk-XIOMMGPD.cjs → chunk-TFOPHZ3U.cjs} +1 -1
- package/dist/chunk-TFOPHZ3U.cjs.map +1 -0
- package/dist/{chunk-Z4BC6M74.js → chunk-UBIXVXPR.js} +2 -2
- package/dist/{chunk-BLWCAQCW.js → chunk-VXR7XWMF.js} +4574 -770
- package/dist/chunk-VXR7XWMF.js.map +1 -0
- package/dist/{chunk-CZOXTEMN.js → chunk-XICA4PVO.js} +392 -421
- package/dist/chunk-XICA4PVO.js.map +1 -0
- package/dist/{chunk-HNS7UHCM.js → chunk-XK5LZKBD.js} +1 -1
- package/dist/chunk-XK5LZKBD.js.map +1 -0
- package/dist/cms/index.cjs +146 -0
- package/dist/cms/index.cjs.map +1 -0
- package/dist/cms/index.d.cts +51 -0
- package/dist/cms/index.d.ts +51 -0
- package/dist/cms/index.js +146 -0
- package/dist/cms/index.js.map +1 -0
- package/dist/{export-CEXEzqBf.d.cts → export-BJE8T0YA.d.cts} +279 -191
- package/dist/{export-DIkoK8-r.d.ts → export-Con3UKkm.d.ts} +279 -191
- package/dist/image-editor/index.cjs +1848 -1218
- package/dist/image-editor/index.cjs.map +1 -1
- package/dist/image-editor/index.d.cts +85 -93
- package/dist/image-editor/index.d.ts +85 -93
- package/dist/image-editor/index.js +871 -241
- package/dist/image-editor/index.js.map +1 -1
- package/dist/opentype-BZEOSOX3.d.ts +188 -0
- package/dist/opentype-Dpe75vL5.d.cts +188 -0
- package/dist/paint/index.cjs +4 -4
- package/dist/paint/index.d.cts +2 -2
- package/dist/paint/index.d.ts +2 -2
- package/dist/paint/index.js +3 -3
- package/dist/paint-editor/index.cjs +147 -145
- package/dist/paint-editor/index.cjs.map +1 -1
- package/dist/paint-editor/index.d.cts +9 -8
- package/dist/paint-editor/index.d.ts +9 -8
- package/dist/paint-editor/index.js +7 -5
- package/dist/paint-editor/index.js.map +1 -1
- package/dist/raster/index.cjs +53 -3
- package/dist/raster/index.cjs.map +1 -1
- package/dist/raster/index.d.cts +62 -91
- package/dist/raster/index.d.ts +62 -91
- package/dist/raster/index.js +59 -9
- package/dist/{render-BEriFuqK.d.cts → render-B1K_OoLy.d.cts} +87 -2
- package/dist/{render-tjzKaik-.d.ts → render-CrmHOgpo.d.ts} +87 -2
- package/dist/{retouch-CEIKR22W.d.cts → retouch-Bxkuc0KH.d.cts} +1 -1
- package/dist/{retouch-BXmeSCaB.d.ts → retouch-Do6tBs2H.d.ts} +1 -1
- package/dist/{surface-C8RRg_Bh.d.cts → surface-Cn30xIV6.d.cts} +6 -1
- package/dist/{surface-C8RRg_Bh.d.ts → surface-Cn30xIV6.d.ts} +6 -1
- package/dist/{svg-D_cfkhlB.d.cts → svg-BnRj0q8i.d.cts} +16 -4
- package/dist/{svg-wIaKLrU0.d.ts → svg-CmmBFfGT.d.ts} +16 -4
- package/dist/{types-DtL_qLFz.d.ts → types-1SUQKDAw.d.ts} +273 -4
- package/dist/{types-DyQq-WPY.d.cts → types-yINF17Ta.d.cts} +273 -4
- package/dist/vector/index.cjs +12170 -7343
- package/dist/vector/index.cjs.map +1 -1
- package/dist/vector/index.d.cts +1579 -16
- package/dist/vector/index.d.ts +1579 -16
- package/dist/vector/index.js +6303 -1476
- package/dist/vector/index.js.map +1 -1
- package/dist/warp-B39VsOtd.d.cts +348 -0
- package/dist/warp-DMN30aY6.d.ts +348 -0
- package/dist/zlib-dxQdgHyN.d.cts +95 -0
- package/dist/zlib-dxQdgHyN.d.ts +95 -0
- package/package.json +9 -2
- package/skills/pixerate-image-editor/SKILL.md +13 -36
- package/skills/pixerate-image-editor/references/color-management.md +42 -0
- package/skills/pixerate-image-editor/references/photoshop-files.md +41 -0
- package/skills/pixerate-paint-editor/SKILL.md +136 -4
- package/skills/pixerate-vector/SKILL.md +72 -2
- package/dist/chunk-BLWCAQCW.js.map +0 -1
- package/dist/chunk-CZOXTEMN.js.map +0 -1
- package/dist/chunk-HNS7UHCM.js.map +0 -1
- package/dist/chunk-JLYX4V57.cjs +0 -2001
- package/dist/chunk-JLYX4V57.cjs.map +0 -1
- package/dist/chunk-KB2YBCVS.js +0 -2001
- package/dist/chunk-KB2YBCVS.js.map +0 -1
- package/dist/chunk-LQEEDHOP.js.map +0 -1
- package/dist/chunk-POGBUYWE.cjs.map +0 -1
- package/dist/chunk-W3GXSUSQ.cjs.map +0 -1
- package/dist/chunk-XIOMMGPD.cjs.map +0 -1
- package/dist/chunk-YGIMK4NX.cjs.map +0 -1
- package/dist/homography-CZ-tFjay.d.cts +0 -50
- package/dist/homography-Ctfjoc1b.d.ts +0 -50
- package/dist/warp-CWHZzE3x.d.ts +0 -118
- package/dist/warp-D5jz_tN7.d.cts +0 -118
- /package/dist/{chunk-LPYOIVLA.js.map → chunk-LKCYANMW.js.map} +0 -0
- /package/dist/{chunk-Z4BC6M74.js.map → chunk-UBIXVXPR.js.map} +0 -0
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
DEFAULT_GLOBAL_LIGHT,
|
|
3
|
+
DeepCompositor,
|
|
3
4
|
LAYER_EFFECT_KINDS,
|
|
4
5
|
LayerEffectError,
|
|
5
6
|
MAX_EFFECT_REACH,
|
|
6
7
|
PatternTile,
|
|
7
8
|
RasterCompositor,
|
|
8
9
|
TransformTooLargeError,
|
|
9
|
-
ZlibError,
|
|
10
10
|
base64ToBytes,
|
|
11
11
|
blendTile,
|
|
12
12
|
builtinPattern,
|
|
@@ -23,7 +23,6 @@ import {
|
|
|
23
23
|
findLayer,
|
|
24
24
|
flattenLayers,
|
|
25
25
|
gaussianBlur,
|
|
26
|
-
inflate,
|
|
27
26
|
insertLayer,
|
|
28
27
|
isInterpolation,
|
|
29
28
|
isLayerEffectKind,
|
|
@@ -35,13 +34,17 @@ import {
|
|
|
35
34
|
parseDataUrl,
|
|
36
35
|
parseEffectColor,
|
|
37
36
|
pngDataUrl,
|
|
37
|
+
readDeepRegion,
|
|
38
38
|
reduceSurface,
|
|
39
39
|
scaleLayerEffect,
|
|
40
|
+
surfaceDepth,
|
|
41
|
+
surfaceFromDeepPixels,
|
|
40
42
|
transformSurface,
|
|
41
43
|
validateEffectGradient,
|
|
42
44
|
validateLayerEffects,
|
|
43
|
-
warpSurface
|
|
44
|
-
|
|
45
|
+
warpSurface,
|
|
46
|
+
writeDeepRegion
|
|
47
|
+
} from "./chunk-C6C5PDKU.js";
|
|
45
48
|
import {
|
|
46
49
|
affineFromHomography,
|
|
47
50
|
applyHomography,
|
|
@@ -68,8 +71,21 @@ import {
|
|
|
68
71
|
tileKey,
|
|
69
72
|
tilesInRect,
|
|
70
73
|
translateSurface
|
|
71
|
-
} from "./chunk-
|
|
74
|
+
} from "./chunk-XK5LZKBD.js";
|
|
75
|
+
import {
|
|
76
|
+
Transform,
|
|
77
|
+
builtinProfile,
|
|
78
|
+
parseProfile,
|
|
79
|
+
srgbProfile
|
|
80
|
+
} from "./chunk-BRLYOPLT.js";
|
|
81
|
+
import {
|
|
82
|
+
ZlibError,
|
|
83
|
+
deflate,
|
|
84
|
+
inflate
|
|
85
|
+
} from "./chunk-6FCKOS2B.js";
|
|
72
86
|
import {
|
|
87
|
+
DEFAULT_AUTO_LEADING,
|
|
88
|
+
DEFAULT_TEXT_STYLE,
|
|
73
89
|
IDENTITY_MATRIX,
|
|
74
90
|
WARP_STYLES,
|
|
75
91
|
applyMatrix,
|
|
@@ -77,11 +93,15 @@ import {
|
|
|
77
93
|
ellipseSubpath,
|
|
78
94
|
evalWarpMesh,
|
|
79
95
|
expandVectorCorners,
|
|
96
|
+
fitParagraphRuns,
|
|
97
|
+
fitRuns,
|
|
80
98
|
fitWarpMesh,
|
|
81
99
|
identityWarpMesh,
|
|
82
100
|
invertMatrix,
|
|
83
101
|
isIdentityMatrix,
|
|
102
|
+
isTextSpace,
|
|
84
103
|
isValidWarpMesh,
|
|
104
|
+
layoutText,
|
|
85
105
|
mapWarpMeshPoints,
|
|
86
106
|
matrixAbout,
|
|
87
107
|
multiplyMatrices,
|
|
@@ -89,11 +109,16 @@ import {
|
|
|
89
109
|
rectSubpath,
|
|
90
110
|
rotateMatrix,
|
|
91
111
|
setAnchorCorner,
|
|
112
|
+
spliceRuns,
|
|
92
113
|
starSubpath,
|
|
114
|
+
styleAt,
|
|
93
115
|
subpathsToBezier,
|
|
116
|
+
textDecorations,
|
|
117
|
+
textFragmentOutline,
|
|
118
|
+
textRectPath,
|
|
94
119
|
translateMatrix,
|
|
95
120
|
warpPresetMesh
|
|
96
|
-
} from "./chunk-
|
|
121
|
+
} from "./chunk-VXR7XWMF.js";
|
|
97
122
|
import {
|
|
98
123
|
bezierPathBounds,
|
|
99
124
|
outlineStroke,
|
|
@@ -1742,7 +1767,7 @@ function lutOp(luts) {
|
|
|
1742
1767
|
var isIdentityCurve = (pts) => pts.length === 2 && pts[0].input === 0 && pts[0].output === 0 && pts[1].input === 255 && pts[1].output === 255;
|
|
1743
1768
|
var isIdentityLevels = (c) => c.inBlack === 0 && c.inWhite === 255 && c.gamma === 1 && c.outBlack === 0 && c.outWhite === 255;
|
|
1744
1769
|
var LEVELS_QUANTUM = 255;
|
|
1745
|
-
function toneLuts(layer) {
|
|
1770
|
+
function toneLuts(layer, quantum = LEVELS_QUANTUM) {
|
|
1746
1771
|
const n = ADJUSTMENT_LUT_SIZE;
|
|
1747
1772
|
if (layer.kind === "curves") {
|
|
1748
1773
|
const m = curveLutFromLevels(layer.params.master);
|
|
@@ -1757,13 +1782,14 @@ function toneLuts(layer) {
|
|
|
1757
1782
|
return [layer.params.red, layer.params.green, layer.params.blue].map((rec) => {
|
|
1758
1783
|
const c = toUnitLevels(rec);
|
|
1759
1784
|
const out = new Float32Array(n);
|
|
1760
|
-
|
|
1785
|
+
const q2 = quantum ?? void 0;
|
|
1786
|
+
for (let k = 0; k < n; k++) out[k] = levelsValue(m, levelsValue(c, k / (n - 1), q2), q2);
|
|
1761
1787
|
return out;
|
|
1762
1788
|
});
|
|
1763
1789
|
}
|
|
1764
1790
|
return null;
|
|
1765
1791
|
}
|
|
1766
|
-
function compileAdjustmentLayer(layer) {
|
|
1792
|
+
function compileAdjustmentLayer(layer, options = {}) {
|
|
1767
1793
|
switch (layer.kind) {
|
|
1768
1794
|
case "curves": {
|
|
1769
1795
|
const p = layer.params;
|
|
@@ -1773,7 +1799,7 @@ function compileAdjustmentLayer(layer) {
|
|
|
1773
1799
|
case "levels": {
|
|
1774
1800
|
const p = layer.params;
|
|
1775
1801
|
if ([p.master, p.red, p.green, p.blue].every(isIdentityLevels)) return null;
|
|
1776
|
-
return lutOp(toneLuts(layer));
|
|
1802
|
+
return lutOp(toneLuts(layer, options.deep ? null : LEVELS_QUANTUM));
|
|
1777
1803
|
}
|
|
1778
1804
|
case "hueSaturation": {
|
|
1779
1805
|
const p = layer.params;
|
|
@@ -1878,15 +1904,15 @@ function compileAdjustmentLayer(layer) {
|
|
|
1878
1904
|
}
|
|
1879
1905
|
var COMPILE_CACHE_LIMIT = 64;
|
|
1880
1906
|
var compileCache = /* @__PURE__ */ new Map();
|
|
1881
|
-
function compiledFor(layer) {
|
|
1882
|
-
const key = `${layer.kind}:${JSON.stringify(layer.params)}`;
|
|
1907
|
+
function compiledFor(layer, deep = false) {
|
|
1908
|
+
const key = `${deep ? "deep:" : ""}${layer.kind}:${JSON.stringify(layer.params)}`;
|
|
1883
1909
|
if (compileCache.has(key)) {
|
|
1884
1910
|
const op2 = compileCache.get(key);
|
|
1885
1911
|
compileCache.delete(key);
|
|
1886
1912
|
compileCache.set(key, op2);
|
|
1887
1913
|
return op2;
|
|
1888
1914
|
}
|
|
1889
|
-
const op = compileAdjustmentLayer(layer);
|
|
1915
|
+
const op = compileAdjustmentLayer(layer, { deep });
|
|
1890
1916
|
compileCache.set(key, op);
|
|
1891
1917
|
if (compileCache.size > COMPILE_CACHE_LIMIT) compileCache.delete(compileCache.keys().next().value);
|
|
1892
1918
|
return op;
|
|
@@ -1947,6 +1973,29 @@ function applyAdjustmentLayers(imageData, layers, masks) {
|
|
|
1947
1973
|
data[i + 2] = Math.round(clamp01(c[2]) * 255);
|
|
1948
1974
|
}
|
|
1949
1975
|
}
|
|
1976
|
+
function applyAdjustmentLayersFloat(data, layers, masks) {
|
|
1977
|
+
const active = activeAdjustmentLayers(layers);
|
|
1978
|
+
if (!active.length) return;
|
|
1979
|
+
const ops = active.map((l) => compiledFor(l, true));
|
|
1980
|
+
const planes = active.map((l) => masks?.get(l.id));
|
|
1981
|
+
const c = [0, 0, 0];
|
|
1982
|
+
for (let i = 0; i < data.length; i += 4) {
|
|
1983
|
+
if (!(data[i + 3] > 0)) continue;
|
|
1984
|
+
c[0] = data[i];
|
|
1985
|
+
c[1] = data[i + 1];
|
|
1986
|
+
c[2] = data[i + 2];
|
|
1987
|
+
for (let k = 0; k < active.length; k++) {
|
|
1988
|
+
const plane = planes[k];
|
|
1989
|
+
if (plane) {
|
|
1990
|
+
const cov = plane[i >> 2];
|
|
1991
|
+
if (cov > 0) applyLayer(c, active[k], ops[k], cov >= 1 ? 1 : cov);
|
|
1992
|
+
} else applyLayer(c, active[k], ops[k]);
|
|
1993
|
+
}
|
|
1994
|
+
data[i] = c[0];
|
|
1995
|
+
data[i + 1] = c[1];
|
|
1996
|
+
data[i + 2] = c[2];
|
|
1997
|
+
}
|
|
1998
|
+
}
|
|
1950
1999
|
function adjustmentLayersKey(layers) {
|
|
1951
2000
|
if (!layers?.length) return "";
|
|
1952
2001
|
return JSON.stringify(
|
|
@@ -2222,10 +2271,12 @@ function removeAlpha(imageData) {
|
|
|
2222
2271
|
}
|
|
2223
2272
|
}
|
|
2224
2273
|
|
|
2274
|
+
// src/text/types.ts
|
|
2275
|
+
var TEXT_ALIGNS = ["left", "center", "right", "justify"];
|
|
2276
|
+
|
|
2225
2277
|
// src/image-editor/layers/model.ts
|
|
2226
2278
|
var SHAPE_OPERATIONS = ["combine", "subtract", "intersect", "exclude"];
|
|
2227
2279
|
var LIVE_SHAPE_KINDS = ["rect", "ellipse", "polygon", "star", "line"];
|
|
2228
|
-
var TEXT_ALIGNS = ["left", "center", "right", "justify"];
|
|
2229
2280
|
var idCounter = 0;
|
|
2230
2281
|
function newLayerId(prefix = "layer") {
|
|
2231
2282
|
return `${prefix}_${Date.now().toString(36)}_${(++idCounter).toString(36)}`;
|
|
@@ -2376,6 +2427,12 @@ var LayerCompositor = class extends RasterCompositor {
|
|
|
2376
2427
|
super(PHOTO_PROFILE, options);
|
|
2377
2428
|
}
|
|
2378
2429
|
};
|
|
2430
|
+
function compositeDeep(layers, rect, sources, depth) {
|
|
2431
|
+
const deep = new DeepCompositor(new LayerCompositor(), PHOTO_PROFILE, {
|
|
2432
|
+
applyFilterRunDeep: (run, acc, _r, masks) => applyAdjustmentLayersFloat(acc, run.map(adjustmentNodeAsLayer), masks)
|
|
2433
|
+
}, depth);
|
|
2434
|
+
return deep.composite(layers, rect, sources);
|
|
2435
|
+
}
|
|
2379
2436
|
|
|
2380
2437
|
// src/image-editor/layers/vector-raster.ts
|
|
2381
2438
|
var FLATNESS = 0.01;
|
|
@@ -3901,300 +3958,6 @@ function annotationOfShape(layer) {
|
|
|
3901
3958
|
var fail3 = (message) => {
|
|
3902
3959
|
throw new LayerOperationError(message);
|
|
3903
3960
|
};
|
|
3904
|
-
var DEFAULT_TEXT_STYLE = { fontFamily: "sans-serif", fontWeight: 400, fontSize: 24, color: "#000000" };
|
|
3905
|
-
var DEFAULT_AUTO_LEADING = 1.2;
|
|
3906
|
-
var sameStyle = (a, b) => JSON.stringify(a) === JSON.stringify(b);
|
|
3907
|
-
function compact(runs) {
|
|
3908
|
-
const out = [];
|
|
3909
|
-
for (const r of runs) {
|
|
3910
|
-
if (r.length <= 0) continue;
|
|
3911
|
-
const last = out[out.length - 1];
|
|
3912
|
-
if (last && sameStyle(last.style, r.style)) out[out.length - 1] = { ...last, length: last.length + r.length };
|
|
3913
|
-
else out.push({ ...r });
|
|
3914
|
-
}
|
|
3915
|
-
return out;
|
|
3916
|
-
}
|
|
3917
|
-
function fitRuns(runs, length, fallback) {
|
|
3918
|
-
const out = [];
|
|
3919
|
-
let left = length;
|
|
3920
|
-
for (const r of runs) {
|
|
3921
|
-
if (left <= 0) break;
|
|
3922
|
-
const n = Math.min(Math.max(0, Math.floor(r.length)), left);
|
|
3923
|
-
if (n > 0) out.push({ ...r, length: n });
|
|
3924
|
-
left -= n;
|
|
3925
|
-
}
|
|
3926
|
-
if (left > 0) {
|
|
3927
|
-
if (out.length) out[out.length - 1] = { ...out[out.length - 1], length: out[out.length - 1].length + left };
|
|
3928
|
-
else out.push({ length: left, style: runs[runs.length - 1]?.style ?? fallback });
|
|
3929
|
-
}
|
|
3930
|
-
return compact(out);
|
|
3931
|
-
}
|
|
3932
|
-
function styleAt(runs, index, fallback) {
|
|
3933
|
-
let at = 0;
|
|
3934
|
-
for (const r of runs) {
|
|
3935
|
-
if (index < at + r.length) return r.style;
|
|
3936
|
-
at += r.length;
|
|
3937
|
-
}
|
|
3938
|
-
return runs[runs.length - 1]?.style ?? fallback;
|
|
3939
|
-
}
|
|
3940
|
-
function restyleRange(runs, start, end, patch) {
|
|
3941
|
-
const out = [];
|
|
3942
|
-
let at = 0;
|
|
3943
|
-
for (const r of runs) {
|
|
3944
|
-
const a = at;
|
|
3945
|
-
const b = at + r.length;
|
|
3946
|
-
at = b;
|
|
3947
|
-
const lo = Math.max(a, start);
|
|
3948
|
-
const hi = Math.min(b, end);
|
|
3949
|
-
if (hi <= lo) {
|
|
3950
|
-
out.push({ ...r });
|
|
3951
|
-
continue;
|
|
3952
|
-
}
|
|
3953
|
-
if (lo > a) out.push({ length: lo - a, style: r.style });
|
|
3954
|
-
out.push({ length: hi - lo, style: patch(r.style) });
|
|
3955
|
-
if (b > hi) out.push({ length: b - hi, style: r.style });
|
|
3956
|
-
}
|
|
3957
|
-
return compact(out);
|
|
3958
|
-
}
|
|
3959
|
-
function spliceRuns(runs, start, end, inserted, style) {
|
|
3960
|
-
const out = [];
|
|
3961
|
-
let at = 0;
|
|
3962
|
-
let placed = false;
|
|
3963
|
-
for (const r of runs) {
|
|
3964
|
-
const a = at;
|
|
3965
|
-
const b = at + r.length;
|
|
3966
|
-
at = b;
|
|
3967
|
-
if (b <= start) {
|
|
3968
|
-
out.push({ ...r });
|
|
3969
|
-
continue;
|
|
3970
|
-
}
|
|
3971
|
-
if (a < start) out.push({ length: start - a, style: r.style });
|
|
3972
|
-
if (!placed) {
|
|
3973
|
-
out.push({ length: inserted, style });
|
|
3974
|
-
placed = true;
|
|
3975
|
-
}
|
|
3976
|
-
if (b > end) out.push({ length: b - Math.max(end, a), style: r.style });
|
|
3977
|
-
}
|
|
3978
|
-
if (!placed) out.push({ length: inserted, style });
|
|
3979
|
-
return compact(out);
|
|
3980
|
-
}
|
|
3981
|
-
function paragraphRanges(text3) {
|
|
3982
|
-
const out = [];
|
|
3983
|
-
let start = 0;
|
|
3984
|
-
for (let i = 0; i < text3.length; i++) {
|
|
3985
|
-
if (text3[i] === "\n") {
|
|
3986
|
-
out.push({ start, end: i + 1, content: i });
|
|
3987
|
-
start = i + 1;
|
|
3988
|
-
}
|
|
3989
|
-
}
|
|
3990
|
-
out.push({ start, end: text3.length, content: text3.length });
|
|
3991
|
-
return out;
|
|
3992
|
-
}
|
|
3993
|
-
function fitParagraphRuns(runs, text3) {
|
|
3994
|
-
const fallback = runs[0]?.style ?? {};
|
|
3995
|
-
const out = compact(paragraphRanges(text3).map((p) => ({ length: p.end - p.start, style: styleAt(runs, p.start, fallback) })));
|
|
3996
|
-
return out.length ? out : [{ length: 0, style: fallback }];
|
|
3997
|
-
}
|
|
3998
|
-
function fontOf(style) {
|
|
3999
|
-
const f = { family: style.fontFamily, weight: style.fontWeight, italic: Boolean(style.italic), size: style.fontSize };
|
|
4000
|
-
if (style.postScriptName) f.postScriptName = style.postScriptName;
|
|
4001
|
-
return f;
|
|
4002
|
-
}
|
|
4003
|
-
var isBreakAfter = (c) => c === " " || c === " " || c === "-" || c === "\u2010" || c === "\u200B";
|
|
4004
|
-
var isSpace = (c) => c === " " || c === " ";
|
|
4005
|
-
var isWide = (code) => code >= 11904 && code <= 40959 || code >= 44032 && code <= 55215 || code >= 63744 && code <= 64255 || code >= 65280 && code <= 65519;
|
|
4006
|
-
var layoutCache = /* @__PURE__ */ new WeakMap();
|
|
4007
|
-
function layoutText(layer, shaper) {
|
|
4008
|
-
let byShaper = layoutCache.get(layer);
|
|
4009
|
-
const hit = byShaper?.get(shaper.id);
|
|
4010
|
-
if (hit) return hit;
|
|
4011
|
-
const out = computeLayout(layer, shaper);
|
|
4012
|
-
if (!byShaper) {
|
|
4013
|
-
byShaper = /* @__PURE__ */ new Map();
|
|
4014
|
-
layoutCache.set(layer, byShaper);
|
|
4015
|
-
}
|
|
4016
|
-
byShaper.set(shaper.id, out);
|
|
4017
|
-
return out;
|
|
4018
|
-
}
|
|
4019
|
-
function computeLayout(layer, shaper) {
|
|
4020
|
-
const { text: text3, frame } = layer;
|
|
4021
|
-
const runs = fitRuns(layer.runs, text3.length, DEFAULT_TEXT_STYLE);
|
|
4022
|
-
const missing = /* @__PURE__ */ new Set();
|
|
4023
|
-
const resolved = /* @__PURE__ */ new Map();
|
|
4024
|
-
const familyOf = (font) => {
|
|
4025
|
-
const key = `${font.family}|${font.weight}|${font.italic}|${font.postScriptName ?? ""}`;
|
|
4026
|
-
let fam = resolved.get(key);
|
|
4027
|
-
if (fam === void 0) {
|
|
4028
|
-
const r = shaper.resolve(font);
|
|
4029
|
-
fam = r.family;
|
|
4030
|
-
if (!r.available) missing.add(font.family);
|
|
4031
|
-
resolved.set(key, fam);
|
|
4032
|
-
}
|
|
4033
|
-
return fam;
|
|
4034
|
-
};
|
|
4035
|
-
const resolvedFont = (style) => ({ ...fontOf(style), family: familyOf(fontOf(style)) });
|
|
4036
|
-
const box2 = frame.kind === "box" ? frame : null;
|
|
4037
|
-
const lines = [];
|
|
4038
|
-
let y = 0;
|
|
4039
|
-
let first = true;
|
|
4040
|
-
const paragraphs = paragraphRanges(text3);
|
|
4041
|
-
paragraphs.forEach((para, pi) => {
|
|
4042
|
-
const pstyle = styleAt(layer.paragraphs, para.start, {});
|
|
4043
|
-
const autoLeading = pstyle.autoLeading ?? DEFAULT_AUTO_LEADING;
|
|
4044
|
-
if (pi > 0) y += pstyle.spaceBefore ?? 0;
|
|
4045
|
-
const chars = [];
|
|
4046
|
-
let i = para.start;
|
|
4047
|
-
while (i < para.content) {
|
|
4048
|
-
const style = styleAt(runs, i, DEFAULT_TEXT_STYLE);
|
|
4049
|
-
let j = i + 1;
|
|
4050
|
-
while (j < para.content && styleAt(runs, j, DEFAULT_TEXT_STYLE) === style) j++;
|
|
4051
|
-
const seg = text3.slice(i, j);
|
|
4052
|
-
const carets = shaper.measure(seg, resolvedFont(style));
|
|
4053
|
-
const track = (style.tracking ?? 0) / 1e3 * style.fontSize;
|
|
4054
|
-
for (let k = 0; k < seg.length; k++) chars.push({ index: i + k, ch: seg[k], advance: (carets[k + 1] ?? 0) - (carets[k] ?? 0) + track, style });
|
|
4055
|
-
i = j;
|
|
4056
|
-
}
|
|
4057
|
-
const startIndent = pstyle.startIndent ?? 0;
|
|
4058
|
-
const endIndent = pstyle.endIndent ?? 0;
|
|
4059
|
-
const firstIndent = pstyle.firstLineIndent ?? 0;
|
|
4060
|
-
const breaks = [];
|
|
4061
|
-
if (!box2 || !chars.length) breaks.push([0, chars.length]);
|
|
4062
|
-
else {
|
|
4063
|
-
let s = 0;
|
|
4064
|
-
while (s < chars.length) {
|
|
4065
|
-
const avail = box2.width - startIndent - endIndent - (breaks.length === 0 ? firstIndent : 0);
|
|
4066
|
-
let w = 0;
|
|
4067
|
-
let e = s;
|
|
4068
|
-
let lastBreak = -1;
|
|
4069
|
-
while (e < chars.length) {
|
|
4070
|
-
const c = chars[e];
|
|
4071
|
-
if (!isSpace(c.ch) && w + c.advance > avail && e > s) break;
|
|
4072
|
-
w += c.advance;
|
|
4073
|
-
if (isBreakAfter(c.ch) || isWide(c.ch.charCodeAt(0)) || e + 1 < chars.length && isWide(chars[e + 1].ch.charCodeAt(0))) lastBreak = e + 1;
|
|
4074
|
-
e++;
|
|
4075
|
-
}
|
|
4076
|
-
if (e < chars.length && lastBreak > s) e = lastBreak;
|
|
4077
|
-
while (e < chars.length && isSpace(chars[e].ch)) e++;
|
|
4078
|
-
breaks.push([s, e]);
|
|
4079
|
-
s = e;
|
|
4080
|
-
}
|
|
4081
|
-
}
|
|
4082
|
-
const align = pstyle.align ?? "left";
|
|
4083
|
-
breaks.forEach(([s, e], li) => {
|
|
4084
|
-
const lineChars = chars.slice(s, e);
|
|
4085
|
-
let visibleEnd = lineChars.length;
|
|
4086
|
-
while (visibleEnd > 0 && isSpace(lineChars[visibleEnd - 1].ch)) visibleEnd--;
|
|
4087
|
-
const styles = lineChars.length ? [...new Set(lineChars.map((c) => c.style))] : [styleAt(runs, Math.min(para.start, Math.max(0, text3.length - 1)), DEFAULT_TEXT_STYLE)];
|
|
4088
|
-
let ascent = 0;
|
|
4089
|
-
let descent = 0;
|
|
4090
|
-
let leading = 0;
|
|
4091
|
-
for (const st of styles) {
|
|
4092
|
-
const m = shaper.metrics(resolvedFont(st));
|
|
4093
|
-
ascent = Math.max(ascent, m.ascent);
|
|
4094
|
-
descent = Math.max(descent, m.descent);
|
|
4095
|
-
leading = Math.max(leading, st.leading ?? autoLeading * st.fontSize);
|
|
4096
|
-
}
|
|
4097
|
-
if (first) {
|
|
4098
|
-
y = frame.kind === "box" || frame.kind === "point" && frame.origin === "top" ? ascent : 0;
|
|
4099
|
-
first = false;
|
|
4100
|
-
} else y += leading;
|
|
4101
|
-
const indent = startIndent + (li === 0 ? firstIndent : 0);
|
|
4102
|
-
let width = 0;
|
|
4103
|
-
for (let k2 = 0; k2 < visibleEnd; k2++) width += lineChars[k2].advance;
|
|
4104
|
-
const lastLine = li === breaks.length - 1;
|
|
4105
|
-
let extraPerSpace = 0;
|
|
4106
|
-
if (box2 && align === "justify" && !lastLine) {
|
|
4107
|
-
const spaces = lineChars.slice(0, visibleEnd).filter((c) => isSpace(c.ch)).length;
|
|
4108
|
-
const avail = box2.width - startIndent - endIndent - (li === 0 ? firstIndent : 0);
|
|
4109
|
-
if (spaces > 0 && avail > width) extraPerSpace = (avail - width) / spaces;
|
|
4110
|
-
}
|
|
4111
|
-
let x0;
|
|
4112
|
-
const fullWidth = width + extraPerSpace * lineChars.slice(0, visibleEnd).filter((c) => isSpace(c.ch)).length;
|
|
4113
|
-
if (box2) {
|
|
4114
|
-
const avail = box2.width - startIndent - endIndent - (li === 0 ? firstIndent : 0);
|
|
4115
|
-
x0 = indent + (align === "center" ? (avail - fullWidth) / 2 : align === "right" ? avail - fullWidth : 0);
|
|
4116
|
-
} else x0 = indent + (align === "center" ? -fullWidth / 2 : align === "right" ? -fullWidth : 0);
|
|
4117
|
-
const laid = [];
|
|
4118
|
-
let x = x0;
|
|
4119
|
-
for (const c of lineChars) {
|
|
4120
|
-
const adv = c.advance + (isSpace(c.ch) ? extraPerSpace : 0);
|
|
4121
|
-
laid.push({ index: c.index, x, advance: adv });
|
|
4122
|
-
x += adv;
|
|
4123
|
-
}
|
|
4124
|
-
const fragments = [];
|
|
4125
|
-
let k = 0;
|
|
4126
|
-
while (k < lineChars.length) {
|
|
4127
|
-
const st = lineChars[k].style;
|
|
4128
|
-
let m = k + 1;
|
|
4129
|
-
while (m < lineChars.length && lineChars[m].style === st) m++;
|
|
4130
|
-
const font = resolvedFont(st);
|
|
4131
|
-
const fx = laid[k].x;
|
|
4132
|
-
const carets = [0];
|
|
4133
|
-
for (let q2 = k; q2 < m; q2++) carets.push(laid[q2].x + laid[q2].advance - fx);
|
|
4134
|
-
fragments.push({
|
|
4135
|
-
start: lineChars[k].index,
|
|
4136
|
-
end: lineChars[m - 1].index + 1,
|
|
4137
|
-
style: st,
|
|
4138
|
-
font,
|
|
4139
|
-
family: font.family,
|
|
4140
|
-
x: fx,
|
|
4141
|
-
y: y - (st.baselineShift ?? 0),
|
|
4142
|
-
carets,
|
|
4143
|
-
spaced: Boolean(st.tracking) || extraPerSpace > 0
|
|
4144
|
-
});
|
|
4145
|
-
k = m;
|
|
4146
|
-
}
|
|
4147
|
-
const lineStart = lineChars.length ? lineChars[0].index : para.start;
|
|
4148
|
-
lines.push({ start: lineStart, end: lineChars.length ? lineChars[lineChars.length - 1].index + 1 : para.start, baseline: y, ascent, descent, x: x0, width, chars: laid, fragments });
|
|
4149
|
-
});
|
|
4150
|
-
y += pstyle.spaceAfter ?? 0;
|
|
4151
|
-
});
|
|
4152
|
-
let bounds;
|
|
4153
|
-
if (box2) bounds = { x: 0, y: 0, width: box2.width, height: box2.height };
|
|
4154
|
-
else {
|
|
4155
|
-
let x0 = Infinity;
|
|
4156
|
-
let x1 = -Infinity;
|
|
4157
|
-
for (const l of lines) {
|
|
4158
|
-
x0 = Math.min(x0, l.x);
|
|
4159
|
-
x1 = Math.max(x1, l.x + l.width);
|
|
4160
|
-
}
|
|
4161
|
-
if (!Number.isFinite(x0)) x0 = x1 = 0;
|
|
4162
|
-
const top = lines.length ? lines[0].baseline - lines[0].ascent : 0;
|
|
4163
|
-
const last = lines[lines.length - 1];
|
|
4164
|
-
const bottom = last ? last.baseline + last.descent : 0;
|
|
4165
|
-
bounds = { x: x0, y: top, width: Math.max(0, x1 - x0), height: Math.max(0, bottom - top) };
|
|
4166
|
-
}
|
|
4167
|
-
return { lines, bounds, missingFonts: [...missing] };
|
|
4168
|
-
}
|
|
4169
|
-
function textIndexAt(layout, p) {
|
|
4170
|
-
if (!layout.lines.length) return 0;
|
|
4171
|
-
let line = layout.lines[layout.lines.length - 1];
|
|
4172
|
-
for (const l of layout.lines) {
|
|
4173
|
-
if (p.y <= l.baseline + l.descent) {
|
|
4174
|
-
line = l;
|
|
4175
|
-
break;
|
|
4176
|
-
}
|
|
4177
|
-
}
|
|
4178
|
-
if (!line.chars.length) return line.start;
|
|
4179
|
-
for (const c of line.chars) if (p.x < c.x + c.advance / 2) return c.index;
|
|
4180
|
-
const lastChar = line.chars[line.chars.length - 1];
|
|
4181
|
-
return lastChar.index + 1;
|
|
4182
|
-
}
|
|
4183
|
-
function caretAt(layout, index) {
|
|
4184
|
-
const lines = layout.lines;
|
|
4185
|
-
if (!lines.length) return { x: 0, top: 0, bottom: 0, line: 0 };
|
|
4186
|
-
for (let li = 0; li < lines.length; li++) {
|
|
4187
|
-
const l2 = lines[li];
|
|
4188
|
-
const next = lines[li + 1];
|
|
4189
|
-
if (next && index >= next.start && (next.chars.length || index > l2.end || next.start > l2.end)) continue;
|
|
4190
|
-
const c = l2.chars.find((ch) => ch.index === index);
|
|
4191
|
-
const prev = l2.chars.find((ch) => ch.index === index - 1);
|
|
4192
|
-
const x = c ? c.x : prev ? prev.x + prev.advance : l2.x;
|
|
4193
|
-
return { x, top: l2.baseline - l2.ascent, bottom: l2.baseline + l2.descent, line: li };
|
|
4194
|
-
}
|
|
4195
|
-
const l = lines[lines.length - 1];
|
|
4196
|
-
return { x: l.x + l.width, top: l.baseline - l.ascent, bottom: l.baseline + l.descent, line: lines.length - 1 };
|
|
4197
|
-
}
|
|
4198
3961
|
var TEXT_RENDER_MARGIN = MAX_EFFECT_REACH;
|
|
4199
3962
|
function textMatrix(layer) {
|
|
4200
3963
|
return layer.transform ?? IDENTITY_MATRIX;
|
|
@@ -4239,31 +4002,6 @@ function inkBounds(layout) {
|
|
|
4239
4002
|
}
|
|
4240
4003
|
return b;
|
|
4241
4004
|
}
|
|
4242
|
-
function decorations(f, l) {
|
|
4243
|
-
const out = [];
|
|
4244
|
-
const t = Math.max(1, f.style.fontSize / 15);
|
|
4245
|
-
const w = f.carets[f.carets.length - 1];
|
|
4246
|
-
if (f.style.underline) out.push({ x: f.x, y: f.y + Math.max(t, l.descent * 0.35), width: w, height: t });
|
|
4247
|
-
if (f.style.strikethrough) out.push({ x: f.x, y: f.y - l.ascent * 0.3 - t / 2, width: w, height: t });
|
|
4248
|
-
return out;
|
|
4249
|
-
}
|
|
4250
|
-
var rectPath = (r) => [
|
|
4251
|
-
{ type: "M", x: r.x, y: r.y },
|
|
4252
|
-
{ type: "L", x: r.x + r.width, y: r.y },
|
|
4253
|
-
{ type: "L", x: r.x + r.width, y: r.y + r.height },
|
|
4254
|
-
{ type: "L", x: r.x, y: r.y + r.height },
|
|
4255
|
-
{ type: "Z" }
|
|
4256
|
-
];
|
|
4257
|
-
function fragmentOutline(shaper, text3, f) {
|
|
4258
|
-
const s = text3.slice(f.start, f.end);
|
|
4259
|
-
if (!f.spaced) return shaper.outline(s, f.font, f.x, f.y);
|
|
4260
|
-
const out = [];
|
|
4261
|
-
for (let k = 0; k < s.length; k++) {
|
|
4262
|
-
if (isSpace(s[k])) continue;
|
|
4263
|
-
out.push(...shaper.outline(s[k], f.font, f.x + f.carets[k], f.y));
|
|
4264
|
-
}
|
|
4265
|
-
return out;
|
|
4266
|
-
}
|
|
4267
4005
|
function textOutlines(layer, shaper) {
|
|
4268
4006
|
if (!shaper.outline) fail3(`The text shaper "${shaper.id}" cannot give glyph outlines; plug in an outline shaper (createOutlineTextShaper) to convert text to shapes.`);
|
|
4269
4007
|
const layout = layoutText(layer, shaper);
|
|
@@ -4271,8 +4009,8 @@ function textOutlines(layer, shaper) {
|
|
|
4271
4009
|
const out = [];
|
|
4272
4010
|
for (const l of layout.lines) {
|
|
4273
4011
|
for (const f of l.fragments) {
|
|
4274
|
-
let path =
|
|
4275
|
-
for (const r of
|
|
4012
|
+
let path = textFragmentOutline(shaper, layer.text, f);
|
|
4013
|
+
for (const r of textDecorations(f, l)) path = [...path, ...textRectPath(r)];
|
|
4276
4014
|
out.push({ fragment: f, path: isIdentityMatrix(m) ? path : transformBezierPath(path, m) });
|
|
4277
4015
|
}
|
|
4278
4016
|
}
|
|
@@ -4341,8 +4079,8 @@ function renderOnCanvas(layer, shaper, region, env) {
|
|
|
4341
4079
|
ctx.globalAlpha = f.style.opacity ?? 1;
|
|
4342
4080
|
const s = layer.text.slice(f.start, f.end);
|
|
4343
4081
|
if (!f.spaced) shaper.draw(ctx, s, f.font, f.x, f.y);
|
|
4344
|
-
else for (let k = 0; k < s.length; k++) if (!
|
|
4345
|
-
for (const d of
|
|
4082
|
+
else for (let k = 0; k < s.length; k++) if (!isTextSpace(s[k])) shaper.draw(ctx, s[k], f.font, f.x + f.carets[k], f.y);
|
|
4083
|
+
for (const d of textDecorations(f, l)) ctx.fillRect(d.x, d.y, d.width, d.height);
|
|
4346
4084
|
}
|
|
4347
4085
|
}
|
|
4348
4086
|
ctx.globalAlpha = 1;
|
|
@@ -5679,6 +5417,42 @@ function encodeSurface(surface) {
|
|
|
5679
5417
|
encodedCache.set(surface, out);
|
|
5680
5418
|
return out;
|
|
5681
5419
|
}
|
|
5420
|
+
var deepCache = /* @__PURE__ */ new WeakMap();
|
|
5421
|
+
function encodeDeepSurface(surface) {
|
|
5422
|
+
if (deepCache.has(surface)) return deepCache.get(surface);
|
|
5423
|
+
let out = null;
|
|
5424
|
+
const depth = surfaceDepth(surface);
|
|
5425
|
+
const b = depth === 8 ? null : contentBounds(surface);
|
|
5426
|
+
if (depth !== 8 && b) {
|
|
5427
|
+
const samples = readDeepRegion(surface, b, depth);
|
|
5428
|
+
const bytes = new Uint8Array(samples.byteLength);
|
|
5429
|
+
const view = new DataView(bytes.buffer);
|
|
5430
|
+
if (samples instanceof Uint16Array) for (let i = 0; i < samples.length; i++) view.setUint16(2 * i, samples[i], true);
|
|
5431
|
+
else for (let i = 0; i < samples.length; i++) view.setFloat32(4 * i, samples[i], true);
|
|
5432
|
+
out = { depth, x: b.x, y: b.y, width: b.width, height: b.height, data: bytesToBase64(deflate(bytes)) };
|
|
5433
|
+
}
|
|
5434
|
+
deepCache.set(surface, out);
|
|
5435
|
+
return out;
|
|
5436
|
+
}
|
|
5437
|
+
function decodeDeepSurface(surface, raw, problems, label) {
|
|
5438
|
+
const d = raw;
|
|
5439
|
+
if (!d || typeof d !== "object") return surface;
|
|
5440
|
+
try {
|
|
5441
|
+
if (d.depth !== 16 && d.depth !== 32 || !(d.width > 0 && d.height > 0) || !Number.isInteger(d.x) || !Number.isInteger(d.y) || typeof d.data !== "string") throw new Error("malformed");
|
|
5442
|
+
const n = d.width * d.height * 4;
|
|
5443
|
+
const size = d.depth === 16 ? 2 : 4;
|
|
5444
|
+
const bytes = inflate(base64ToBytes(d.data), { maxOutput: n * size });
|
|
5445
|
+
if (bytes.length !== n * size) throw new Error("wrong length");
|
|
5446
|
+
const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
5447
|
+
const samples = d.depth === 16 ? new Uint16Array(n) : new Float32Array(n);
|
|
5448
|
+
if (samples instanceof Uint16Array) for (let i = 0; i < n; i++) samples[i] = view.getUint16(2 * i, true);
|
|
5449
|
+
else for (let i = 0; i < n; i++) samples[i] = view.getFloat32(4 * i, true);
|
|
5450
|
+
return writeDeepRegion(surface, { x: d.x, y: d.y, width: d.width, height: d.height }, samples);
|
|
5451
|
+
} catch {
|
|
5452
|
+
problems.push(`${label}: its ${d.depth}-bit samples could not be read, so it was opened at 8 bits`);
|
|
5453
|
+
return surface;
|
|
5454
|
+
}
|
|
5455
|
+
}
|
|
5682
5456
|
function baseFields(layer, ctx) {
|
|
5683
5457
|
const out = {
|
|
5684
5458
|
id: layer.id,
|
|
@@ -5747,6 +5521,10 @@ function serializeLayer(layer, ctx) {
|
|
|
5747
5521
|
}
|
|
5748
5522
|
if (layer.fillOpacity !== void 0 && layer.fillOpacity !== 1) out.fillOpacity = layer.fillOpacity;
|
|
5749
5523
|
if (layer.filters?.length) out.filters = JSON.parse(JSON.stringify(layer.filters));
|
|
5524
|
+
if (layer.source !== "document") {
|
|
5525
|
+
const deep = encodeDeepSurface(layer.surface);
|
|
5526
|
+
if (deep) out.deep = deep;
|
|
5527
|
+
}
|
|
5750
5528
|
return out;
|
|
5751
5529
|
}
|
|
5752
5530
|
case "adjustment":
|
|
@@ -6128,6 +5906,7 @@ function deserializeLayer(raw, ctx) {
|
|
|
6128
5906
|
offset: { x: Math.round(num2(r.offset?.x, -1e7, 1e7, 0)), y: Math.round(num2(r.offset?.y, -1e7, 1e7, 0)) }
|
|
6129
5907
|
};
|
|
6130
5908
|
if (r.source === "document") layer.source = "document";
|
|
5909
|
+
else if (r.deep) layer.surface = decodeDeepSurface(layer.surface, r.deep, ctx.problems, `Layer "${base.name || id}"`);
|
|
6131
5910
|
if (typeof r.fillOpacity === "number" && r.fillOpacity !== 1) layer.fillOpacity = num2(r.fillOpacity, 0, 1, 1);
|
|
6132
5911
|
const filters = readFilters(r.filters);
|
|
6133
5912
|
if (filters) layer.filters = filters;
|
|
@@ -8465,6 +8244,36 @@ function encodeRle(decoded2, l) {
|
|
|
8465
8244
|
out.set(packed.subarray(0, at), counts.length);
|
|
8466
8245
|
return out;
|
|
8467
8246
|
}
|
|
8247
|
+
function predict(buf, l) {
|
|
8248
|
+
const rb = rowBytes(l.width, l.depth);
|
|
8249
|
+
if (rb === 0) return;
|
|
8250
|
+
const w = l.width;
|
|
8251
|
+
const scratch = l.depth === 32 ? new Uint8Array(rb) : null;
|
|
8252
|
+
for (let o = 0; o + rb <= buf.length; o += rb) {
|
|
8253
|
+
if (l.depth === 1 || l.depth === 8) {
|
|
8254
|
+
for (let i = rb - 1; i > 0; i--) buf[o + i] = buf[o + i] - buf[o + i - 1] & 255;
|
|
8255
|
+
} else if (l.depth === 16) {
|
|
8256
|
+
for (let i = w - 1; i > 0; i--) {
|
|
8257
|
+
const a = buf[o + 2 * i] << 8 | buf[o + 2 * i + 1];
|
|
8258
|
+
const b = buf[o + 2 * i - 2] << 8 | buf[o + 2 * i - 1];
|
|
8259
|
+
const v = a - b & 65535;
|
|
8260
|
+
buf[o + 2 * i] = v >> 8;
|
|
8261
|
+
buf[o + 2 * i + 1] = v & 255;
|
|
8262
|
+
}
|
|
8263
|
+
} else if (l.depth === 32) {
|
|
8264
|
+
scratch.set(buf.subarray(o, o + rb));
|
|
8265
|
+
for (let i = 0; i < w; i++) for (let k = 0; k < 4; k++) buf[o + k * w + i] = scratch[4 * i + k];
|
|
8266
|
+
for (let i = rb - 1; i > 0; i--) buf[o + i] = buf[o + i] - buf[o + i - 1] & 255;
|
|
8267
|
+
} else {
|
|
8268
|
+
throw new PsdError(`ZIP prediction is not defined for depth ${l.depth}.`);
|
|
8269
|
+
}
|
|
8270
|
+
}
|
|
8271
|
+
}
|
|
8272
|
+
function encodeZipPredicted(decoded2, l) {
|
|
8273
|
+
const buf = decoded2.slice();
|
|
8274
|
+
predict(buf, l);
|
|
8275
|
+
return deflate(buf);
|
|
8276
|
+
}
|
|
8468
8277
|
|
|
8469
8278
|
// src/image-editor/psd/smart.ts
|
|
8470
8279
|
var dbl2 = (value) => ({ type: "doub", value });
|
|
@@ -9405,23 +9214,31 @@ function writePsd(file, encodeName) {
|
|
|
9405
9214
|
w.endLen(res);
|
|
9406
9215
|
const lm = w.beginLen(psb);
|
|
9407
9216
|
if (file.layers.length || file.globalBlocks.length) {
|
|
9408
|
-
const
|
|
9409
|
-
|
|
9410
|
-
|
|
9411
|
-
|
|
9412
|
-
for (const rec of file.layers) writeLayerRecord(w, rec, psb, encodeName(rec.legacyName));
|
|
9217
|
+
const writeLayerInfo = (out) => {
|
|
9218
|
+
const start = out.length;
|
|
9219
|
+
out.i16(file.mergedAlpha ? -file.layers.length : file.layers.length);
|
|
9220
|
+
for (const rec of file.layers) writeLayerRecord(out, rec, psb, encodeName(rec.legacyName));
|
|
9413
9221
|
for (const rec of file.layers) {
|
|
9414
9222
|
for (const c of rec.channels) {
|
|
9415
9223
|
if (c.compression === null) continue;
|
|
9416
|
-
|
|
9417
|
-
|
|
9224
|
+
out.u16(c.compression);
|
|
9225
|
+
out.bytes(c.data);
|
|
9418
9226
|
}
|
|
9419
9227
|
}
|
|
9420
|
-
if ((
|
|
9421
|
-
}
|
|
9228
|
+
if ((out.length - start) % 2) out.u8(0);
|
|
9229
|
+
};
|
|
9230
|
+
const deepKey = header.depth === 16 ? "Lr16" : header.depth === 32 ? "Lr32" : null;
|
|
9231
|
+
let blocks = file.globalBlocks;
|
|
9232
|
+
const li = w.beginLen(psb);
|
|
9233
|
+
if (file.layers.length && !deepKey) writeLayerInfo(w);
|
|
9422
9234
|
w.endLen(li);
|
|
9235
|
+
if (file.layers.length && deepKey) {
|
|
9236
|
+
const lw = new PsdWriter();
|
|
9237
|
+
writeLayerInfo(lw);
|
|
9238
|
+
blocks = [{ key: deepKey, data: lw.result() }, ...blocks];
|
|
9239
|
+
}
|
|
9423
9240
|
w.u32(0);
|
|
9424
|
-
writeBlocks(w,
|
|
9241
|
+
writeBlocks(w, blocks, psb, 4);
|
|
9425
9242
|
}
|
|
9426
9243
|
w.endLen(lm);
|
|
9427
9244
|
w.u16(file.imageCompression);
|
|
@@ -9430,6 +9247,7 @@ function writePsd(file, encodeName) {
|
|
|
9430
9247
|
}
|
|
9431
9248
|
|
|
9432
9249
|
// src/image-editor/psd/pixels.ts
|
|
9250
|
+
var MODE_BITMAP = 0;
|
|
9433
9251
|
var MODE_INDEXED = 2;
|
|
9434
9252
|
var MODE_RGB = 3;
|
|
9435
9253
|
var MODE_CMYK = 4;
|
|
@@ -9509,6 +9327,15 @@ function toRgba8(set) {
|
|
|
9509
9327
|
}
|
|
9510
9328
|
return out;
|
|
9511
9329
|
}
|
|
9330
|
+
if (mode === MODE_CMYK && set.cmykToRgb) {
|
|
9331
|
+
const ink = new Uint8Array(n * 4);
|
|
9332
|
+
for (let i = 0, o = 0; i < n; i++, o += 4) {
|
|
9333
|
+
for (let c = 0; c < 4; c++) ink[o + c] = Math.round((1 - (planes[c] ? planes[c](i) : 1)) * 255);
|
|
9334
|
+
out[o + 3] = Math.round(alpha(i) * 255);
|
|
9335
|
+
}
|
|
9336
|
+
set.cmykToRgb(ink, out);
|
|
9337
|
+
return out;
|
|
9338
|
+
}
|
|
9512
9339
|
const palette = set.palette;
|
|
9513
9340
|
for (let i = 0, o = 0; i < n; i++, o += 4) {
|
|
9514
9341
|
let r;
|
|
@@ -9553,6 +9380,99 @@ function toRgba8(set) {
|
|
|
9553
9380
|
}
|
|
9554
9381
|
return out;
|
|
9555
9382
|
}
|
|
9383
|
+
function toRgbaDeep(set) {
|
|
9384
|
+
const { width, height, depth, mode } = set;
|
|
9385
|
+
if (depth !== 16 && depth !== 32 || mode === MODE_INDEXED || mode === MODE_BITMAP) return null;
|
|
9386
|
+
const n = width * height;
|
|
9387
|
+
const isLab = mode === MODE_LAB;
|
|
9388
|
+
const cmyk = mode === MODE_CMYK;
|
|
9389
|
+
const raw = (plane, fill) => {
|
|
9390
|
+
if (!plane) return () => fill;
|
|
9391
|
+
if (depth === 16) return (i) => (plane[2 * i] << 8 | plane[2 * i + 1]) / 65535;
|
|
9392
|
+
const view = new DataView(plane.buffer, plane.byteOffset, plane.byteLength);
|
|
9393
|
+
return (i) => view.getFloat32(4 * i, false) || 0;
|
|
9394
|
+
};
|
|
9395
|
+
const planes = set.color.map((p) => raw(p, cmyk ? 1 : 0));
|
|
9396
|
+
const alpha = raw(set.alpha, 1);
|
|
9397
|
+
if (depth === 16) {
|
|
9398
|
+
const out2 = new Uint16Array(n * 4);
|
|
9399
|
+
const q2 = (v) => Math.round(clamp012(v) * 65535);
|
|
9400
|
+
for (let i = 0, o = 0; i < n; i++, o += 4) {
|
|
9401
|
+
let r;
|
|
9402
|
+
let g;
|
|
9403
|
+
let b;
|
|
9404
|
+
if (mode === MODE_CMYK) {
|
|
9405
|
+
const k = planes[3] ? planes[3](i) : 1;
|
|
9406
|
+
r = planes[0](i) * k;
|
|
9407
|
+
g = planes[1](i) * k;
|
|
9408
|
+
b = planes[2](i) * k;
|
|
9409
|
+
} else if (isLab) {
|
|
9410
|
+
[r, g, b] = labToSrgb(planes[0](i) * 100, planes[1](i) * 255 - 128, planes[2](i) * 255 - 128);
|
|
9411
|
+
} else if (mode === MODE_RGB || mode === MODE_MULTICHANNEL) {
|
|
9412
|
+
r = planes[0](i);
|
|
9413
|
+
g = planes[1] ? planes[1](i) : r;
|
|
9414
|
+
b = planes[2] ? planes[2](i) : r;
|
|
9415
|
+
} else r = g = b = planes[0](i);
|
|
9416
|
+
out2[o] = q2(r);
|
|
9417
|
+
out2[o + 1] = q2(g);
|
|
9418
|
+
out2[o + 2] = q2(b);
|
|
9419
|
+
out2[o + 3] = q2(alpha(i));
|
|
9420
|
+
}
|
|
9421
|
+
return out2;
|
|
9422
|
+
}
|
|
9423
|
+
const out = new Float32Array(n * 4);
|
|
9424
|
+
for (let i = 0, o = 0; i < n; i++, o += 4) {
|
|
9425
|
+
let r;
|
|
9426
|
+
let g;
|
|
9427
|
+
let b;
|
|
9428
|
+
if (isLab) {
|
|
9429
|
+
[r, g, b] = labToSrgb(planes[0](i) * 100, planes[1](i) * 255 - 128, planes[2](i) * 255 - 128).map(srgbToLinear);
|
|
9430
|
+
} else if (cmyk) {
|
|
9431
|
+
const k = planes[3] ? planes[3](i) : 1;
|
|
9432
|
+
r = planes[0](i) * k;
|
|
9433
|
+
g = planes[1](i) * k;
|
|
9434
|
+
b = planes[2](i) * k;
|
|
9435
|
+
} else if (mode === MODE_RGB || mode === MODE_MULTICHANNEL) {
|
|
9436
|
+
r = planes[0](i);
|
|
9437
|
+
g = planes[1] ? planes[1](i) : r;
|
|
9438
|
+
b = planes[2] ? planes[2](i) : r;
|
|
9439
|
+
} else r = g = b = planes[0](i);
|
|
9440
|
+
out[o] = r;
|
|
9441
|
+
out[o + 1] = g;
|
|
9442
|
+
out[o + 2] = b;
|
|
9443
|
+
out[o + 3] = clamp012(alpha(i));
|
|
9444
|
+
}
|
|
9445
|
+
return out;
|
|
9446
|
+
}
|
|
9447
|
+
function deepToPlanes(data, n) {
|
|
9448
|
+
const bytes = data instanceof Uint16Array ? 2 : 4;
|
|
9449
|
+
const planes = [0, 1, 2, 3].map(() => new Uint8Array(n * bytes));
|
|
9450
|
+
if (data instanceof Uint16Array) {
|
|
9451
|
+
for (let i = 0; i < n; i++) {
|
|
9452
|
+
for (let c = 0; c < 4; c++) {
|
|
9453
|
+
const v = data[i * 4 + c];
|
|
9454
|
+
planes[c][2 * i] = v >> 8;
|
|
9455
|
+
planes[c][2 * i + 1] = v & 255;
|
|
9456
|
+
}
|
|
9457
|
+
}
|
|
9458
|
+
} else {
|
|
9459
|
+
const views = planes.map((p) => new DataView(p.buffer));
|
|
9460
|
+
for (let i = 0; i < n; i++) for (let c = 0; c < 4; c++) views[c].setFloat32(4 * i, data[i * 4 + c], false);
|
|
9461
|
+
}
|
|
9462
|
+
return planes;
|
|
9463
|
+
}
|
|
9464
|
+
function planeAtDepth(plane, depth) {
|
|
9465
|
+
if (depth === 8) return plane;
|
|
9466
|
+
if (depth === 16) {
|
|
9467
|
+
const out2 = new Uint8Array(plane.length * 2);
|
|
9468
|
+
for (let i = 0; i < plane.length; i++) out2[2 * i] = out2[2 * i + 1] = plane[i];
|
|
9469
|
+
return out2;
|
|
9470
|
+
}
|
|
9471
|
+
const out = new Uint8Array(plane.length * 4);
|
|
9472
|
+
const view = new DataView(out.buffer);
|
|
9473
|
+
for (let i = 0; i < plane.length; i++) view.setFloat32(4 * i, plane[i] / 255, false);
|
|
9474
|
+
return out;
|
|
9475
|
+
}
|
|
9556
9476
|
function toMask8(plane, width, height, depth) {
|
|
9557
9477
|
if (depth === 8) return new Uint8ClampedArray(plane.buffer, plane.byteOffset, width * height);
|
|
9558
9478
|
const s = sampler(plane, depth, width, false, 0);
|
|
@@ -9587,6 +9507,16 @@ function matteWhite(data) {
|
|
|
9587
9507
|
}
|
|
9588
9508
|
return out;
|
|
9589
9509
|
}
|
|
9510
|
+
function matteWhiteDeep(data) {
|
|
9511
|
+
const out = data.slice();
|
|
9512
|
+
const one = out instanceof Uint16Array ? 65535 : 1;
|
|
9513
|
+
for (let i = 0; i < out.length; i += 4) {
|
|
9514
|
+
const a = Math.min(1, Math.max(0, out[i + 3] / one));
|
|
9515
|
+
if (a >= 1) continue;
|
|
9516
|
+
for (let c = 0; c < 3; c++) out[i + c] = out instanceof Uint16Array ? Math.round(out[i + c] * a + one * (1 - a)) : out[i + c] * a + one * (1 - a);
|
|
9517
|
+
}
|
|
9518
|
+
return out;
|
|
9519
|
+
}
|
|
9590
9520
|
|
|
9591
9521
|
// src/image-editor/psd/patterns.ts
|
|
9592
9522
|
var MAX_EDGE = 3e4;
|
|
@@ -9823,16 +9753,19 @@ function recordPixels(ctx, rec, name) {
|
|
|
9823
9753
|
const planes = ids.map((id) => rec.channels.some((c) => c.id === id) ? decodeOr(ctx, rec, id, name) ?? null : void 0);
|
|
9824
9754
|
if (planes.some((p) => p === null)) return emptySurface(4);
|
|
9825
9755
|
if (planes.every((p) => p === void 0)) return emptySurface(4);
|
|
9826
|
-
const
|
|
9756
|
+
const set = {
|
|
9827
9757
|
width,
|
|
9828
9758
|
height,
|
|
9829
9759
|
depth: ctx.file.header.depth,
|
|
9830
9760
|
mode: ctx.file.header.colorMode,
|
|
9831
9761
|
color: planes.slice(0, ctx.colorCount),
|
|
9832
9762
|
alpha: planes[ctx.colorCount],
|
|
9833
|
-
palette: ctx.palette
|
|
9834
|
-
|
|
9835
|
-
|
|
9763
|
+
palette: ctx.palette,
|
|
9764
|
+
cmykToRgb: ctx.cmykToRgb
|
|
9765
|
+
};
|
|
9766
|
+
const deep = set.cmykToRgb ? null : toRgbaDeep(set);
|
|
9767
|
+
if (deep) return surfaceFromDeepPixels({ width, height, data: deep }, 4, rec.rect.left, rec.rect.top);
|
|
9768
|
+
return surfaceFromPixels({ width, height, data: toRgba8(set) }, 4, rec.rect.left, rec.rect.top);
|
|
9836
9769
|
}
|
|
9837
9770
|
function recordMask(ctx, rec, name) {
|
|
9838
9771
|
const m = rec.mask;
|
|
@@ -10230,16 +10163,24 @@ function mergedLayer(ctx) {
|
|
|
10230
10163
|
const plane = (i) => i < header.channels ? planes.subarray(i * size, (i + 1) * size) : void 0;
|
|
10231
10164
|
const cc = ctx.colorCount;
|
|
10232
10165
|
const hasAlpha = header.channels > cc && (ctx.file.layers.length === 0 || ctx.file.mergedAlpha);
|
|
10233
|
-
const
|
|
10166
|
+
const set = {
|
|
10234
10167
|
width,
|
|
10235
10168
|
height,
|
|
10236
10169
|
depth: header.depth,
|
|
10237
10170
|
mode: header.colorMode,
|
|
10238
10171
|
color: Array.from({ length: cc }, (_, i) => plane(i)),
|
|
10239
10172
|
alpha: hasAlpha ? plane(cc) : void 0,
|
|
10240
|
-
palette: ctx.palette
|
|
10241
|
-
|
|
10242
|
-
|
|
10173
|
+
palette: ctx.palette,
|
|
10174
|
+
cmykToRgb: ctx.cmykToRgb
|
|
10175
|
+
};
|
|
10176
|
+
const deep = hasAlpha || set.cmykToRgb ? null : toRgbaDeep(set);
|
|
10177
|
+
let surface;
|
|
10178
|
+
if (deep) surface = surfaceFromDeepPixels({ width, height, data: deep }, 4);
|
|
10179
|
+
else {
|
|
10180
|
+
const data = toRgba8(set);
|
|
10181
|
+
if (hasAlpha) unmatteWhite(data);
|
|
10182
|
+
surface = surfaceFromPixels({ width, height, data }, 4);
|
|
10183
|
+
}
|
|
10243
10184
|
return {
|
|
10244
10185
|
type: "pixel",
|
|
10245
10186
|
id: ctx.newId("Background"),
|
|
@@ -10247,7 +10188,7 @@ function mergedLayer(ctx) {
|
|
|
10247
10188
|
visible: true,
|
|
10248
10189
|
opacity: 1,
|
|
10249
10190
|
blend: "normal",
|
|
10250
|
-
surface
|
|
10191
|
+
surface,
|
|
10251
10192
|
offset: { x: 0, y: 0 }
|
|
10252
10193
|
};
|
|
10253
10194
|
}
|
|
@@ -10270,6 +10211,28 @@ function psdToLayers(file, options = {}) {
|
|
|
10270
10211
|
depth: options.depth ?? 0,
|
|
10271
10212
|
dpi: resolution(file) ?? 72
|
|
10272
10213
|
};
|
|
10214
|
+
let cmykProfile = null;
|
|
10215
|
+
if (header.colorMode === MODE_CMYK && !ctx.skipPixels) {
|
|
10216
|
+
const icc = resource(file, 1039);
|
|
10217
|
+
let src = null;
|
|
10218
|
+
if (icc) {
|
|
10219
|
+
try {
|
|
10220
|
+
const p = parseProfile(icc);
|
|
10221
|
+
if (p.colorSpace === "cmyk") {
|
|
10222
|
+
src = p;
|
|
10223
|
+
cmykProfile = { name: p.description || "Embedded CMYK profile", icc: icc.slice() };
|
|
10224
|
+
} else warn.extra.push(`The CMYK file embeds a ${p.colorSpace.toUpperCase()} profile; the default coated CMYK profile was used.`);
|
|
10225
|
+
} catch (e) {
|
|
10226
|
+
warn.extra.push(`The CMYK profile could not be read (${e instanceof Error ? e.message : String(e)}); the default coated CMYK profile was used.`);
|
|
10227
|
+
}
|
|
10228
|
+
}
|
|
10229
|
+
if (!src) {
|
|
10230
|
+
src = builtinProfile("coated-cmyk");
|
|
10231
|
+
cmykProfile = { builtin: "coated-cmyk", name: src.description };
|
|
10232
|
+
}
|
|
10233
|
+
const t = Transform.create(src, srgbProfile(), { intent: "relative", bpc: true });
|
|
10234
|
+
ctx.cmykToRgb = (ink, out) => t.convert8(ink, 4, out, 4, false);
|
|
10235
|
+
}
|
|
10273
10236
|
for (const block of file.globalBlocks) {
|
|
10274
10237
|
if (LINKED_FILE_KEYS.includes(block.key)) {
|
|
10275
10238
|
for (const f of parseLinkedFiles(block.data)) if (!ctx.linked.has(f.uuid)) ctx.linked.set(f.uuid, f);
|
|
@@ -10291,10 +10254,12 @@ function psdToLayers(file, options = {}) {
|
|
|
10291
10254
|
}
|
|
10292
10255
|
}
|
|
10293
10256
|
const mode = COLOR_MODES[header.colorMode] ?? `mode ${header.colorMode}`;
|
|
10294
|
-
if (mode !== "rgb"
|
|
10295
|
-
warn.extra.push(`The file is ${header.depth}-bit ${mode}; it was converted to
|
|
10257
|
+
if (mode !== "rgb" && header.depth > 8 && header.colorMode !== MODE_INDEXED && header.colorMode !== MODE_BITMAP) {
|
|
10258
|
+
warn.extra.push(`The file is ${header.depth}-bit ${mode}; it was converted to ${header.depth}-bit RGB.`);
|
|
10259
|
+
} else if (mode !== "rgb" || header.depth !== 8 && header.depth !== 16 && header.depth !== 32) {
|
|
10260
|
+
const how = header.colorMode === MODE_CMYK ? ` through ${cmykProfile?.name ?? "its profile"}` : "";
|
|
10261
|
+
warn.extra.push(`The file is ${header.depth}-bit ${mode}; it was converted to 8-bit RGB${how}.`);
|
|
10296
10262
|
}
|
|
10297
|
-
if (resource(file, 1039)) warn.extra.push("The embedded ICC profile is ignored; colours are read as sRGB.");
|
|
10298
10263
|
let layers = [];
|
|
10299
10264
|
if (file.layers.length) {
|
|
10300
10265
|
const tree = layerTree(file);
|
|
@@ -10327,7 +10292,10 @@ function psdToLayers(file, options = {}) {
|
|
|
10327
10292
|
resolution: resolution(file),
|
|
10328
10293
|
patterns: [...ctx.patterns.values()],
|
|
10329
10294
|
...angle !== void 0 || altitude !== void 0 ? { globalLight: { angle: Math.max(-360, Math.min(360, angle ?? 120)), altitude: Math.max(0, Math.min(90, altitude ?? 30)) } } : {},
|
|
10330
|
-
info: { psb: header.psb, depth: header.depth, colorMode: mode, channels: header.channels }
|
|
10295
|
+
info: { psb: header.psb, depth: header.depth, colorMode: mode, channels: header.channels },
|
|
10296
|
+
...cmykProfile ? { sourceMode: { mode: "cmyk", profile: cmykProfile } } : header.colorMode === MODE_LAB ? { sourceMode: { mode: "lab" } } : {},
|
|
10297
|
+
...resource(file, 1039) ? { iccProfile: resource(file, 1039).slice() } : {},
|
|
10298
|
+
bitDepth: (header.depth === 16 || header.depth === 32) && header.colorMode !== MODE_INDEXED && header.colorMode !== MODE_BITMAP ? header.depth : 8
|
|
10331
10299
|
};
|
|
10332
10300
|
}
|
|
10333
10301
|
function importPsd(bytes, options = {}) {
|
|
@@ -11020,11 +10988,18 @@ function sectionBlock(kind, blendKey) {
|
|
|
11020
10988
|
return w.result();
|
|
11021
10989
|
}
|
|
11022
10990
|
var toRect = (r) => ({ top: r.y, left: r.x, bottom: r.y + r.height, right: r.x + r.width });
|
|
11023
|
-
function rleChannel(id, plane, width, height, psb) {
|
|
11024
|
-
|
|
10991
|
+
function rleChannel(id, plane, width, height, psb, depth = 8) {
|
|
10992
|
+
const layout = { planes: 1, width, height, depth, psb };
|
|
10993
|
+
if (depth === 32) return { id, compression: 3, data: encodeZipPredicted(plane, layout) };
|
|
10994
|
+
return { id, compression: 1, data: encodeRle(plane, layout) };
|
|
10995
|
+
}
|
|
10996
|
+
function surfacePlanes(surface, bounds, depth) {
|
|
10997
|
+
const n = bounds.width * bounds.height;
|
|
10998
|
+
if (depth === 8) return rgbaToPlanes(readRegion(surface, bounds), n);
|
|
10999
|
+
return deepToPlanes(readDeepRegion(surface, bounds, depth), n);
|
|
11025
11000
|
}
|
|
11026
11001
|
var emptyChannel = (id) => ({ id, compression: 0, data: new Uint8Array(0) });
|
|
11027
|
-
function maskChannel(mask, ox, oy, psb) {
|
|
11002
|
+
function maskChannel(mask, ox, oy, psb, depth = 8) {
|
|
11028
11003
|
if (mask.source) throw new PsdError("A parametric mask must be baked before export.");
|
|
11029
11004
|
const bounds = contentBounds(mask.surface);
|
|
11030
11005
|
const def = mask.defaultValue;
|
|
@@ -11035,7 +11010,8 @@ function maskChannel(mask, ox, oy, psb) {
|
|
|
11035
11010
|
if (!bounds) return { channel: emptyChannel(CHANNEL_USER_MASK), mask: m };
|
|
11036
11011
|
const plane = readRegion(mask.surface, bounds);
|
|
11037
11012
|
m.rect = toRect({ ...bounds, x: bounds.x + ox, y: bounds.y + oy });
|
|
11038
|
-
|
|
11013
|
+
const bytes = planeAtDepth(new Uint8Array(plane.buffer, plane.byteOffset, plane.length), depth);
|
|
11014
|
+
return { channel: rleChannel(CHANNEL_USER_MASK, bytes, bounds.width, bounds.height, psb, depth), mask: m };
|
|
11039
11015
|
}
|
|
11040
11016
|
function lockBits(layer) {
|
|
11041
11017
|
const l = layer.locks;
|
|
@@ -11114,7 +11090,23 @@ function placedUnchanged(layer, idnt, placedId) {
|
|
|
11114
11090
|
}
|
|
11115
11091
|
function exportPsd(input) {
|
|
11116
11092
|
const { width, height } = input;
|
|
11093
|
+
const depth = input.depth ?? 8;
|
|
11117
11094
|
if (width < 1 || height < 1) throw new PsdError("The document is empty.");
|
|
11095
|
+
const mode = input.colorMode ?? "rgb";
|
|
11096
|
+
if (mode !== "rgb" && !input.colorPlanes) throw new PsdError(`A ${mode.toUpperCase()} file needs colorPlanes to convert the pixels.`);
|
|
11097
|
+
if (mode !== "rgb" && depth !== 8) throw new PsdError(`${mode.toUpperCase()} files are written at 8 bits per channel.`);
|
|
11098
|
+
const colorIds = mode === "cmyk" ? [0, 1, 2, 3] : [0, 1, 2];
|
|
11099
|
+
const colorPlanes = (rgba, n2) => mode === "rgb" ? rgbaToPlanes(rgba, n2).slice(0, 3) : input.colorPlanes(rgba, n2);
|
|
11100
|
+
const pixelChannels = (rgba, w, h) => {
|
|
11101
|
+
const n2 = w * h;
|
|
11102
|
+
const alpha = rgbaToPlanes(rgba, n2)[3];
|
|
11103
|
+
return [rleChannel(CHANNEL_ALPHA, alpha, w, h, psb), ...colorPlanes(rgba, n2).map((p, i) => rleChannel(i, p, w, h, psb))];
|
|
11104
|
+
};
|
|
11105
|
+
const surfaceChannels = (surface, bounds) => {
|
|
11106
|
+
if (mode !== "rgb") return pixelChannels(readRegion(surface, bounds), bounds.width, bounds.height);
|
|
11107
|
+
const [r, g, b, a2] = surfacePlanes(surface, bounds, depth);
|
|
11108
|
+
return [CHANNEL_ALPHA, 0, 1, 2].map((id, i) => rleChannel(id, [a2, r, g, b][i], bounds.width, bounds.height, psb, depth));
|
|
11109
|
+
};
|
|
11118
11110
|
const psb = width > PSD_MAX_DIMENSION || height > PSD_MAX_DIMENSION;
|
|
11119
11111
|
const records = [];
|
|
11120
11112
|
let nextId = 0;
|
|
@@ -11158,7 +11150,7 @@ function exportPsd(input) {
|
|
|
11158
11150
|
case "group": {
|
|
11159
11151
|
records.push({
|
|
11160
11152
|
rect: EMPTY_RECT,
|
|
11161
|
-
channels: [CHANNEL_ALPHA,
|
|
11153
|
+
channels: [CHANNEL_ALPHA, ...colorIds].map(emptyChannel),
|
|
11162
11154
|
blendKey: "norm",
|
|
11163
11155
|
opacity: 255,
|
|
11164
11156
|
clipping: 0,
|
|
@@ -11175,12 +11167,12 @@ function exportPsd(input) {
|
|
|
11175
11167
|
const rec = {
|
|
11176
11168
|
...base,
|
|
11177
11169
|
rect: EMPTY_RECT,
|
|
11178
|
-
channels: [CHANNEL_ALPHA,
|
|
11170
|
+
channels: [CHANNEL_ALPHA, ...colorIds].map(emptyChannel),
|
|
11179
11171
|
blendKey,
|
|
11180
11172
|
flags: base.flags | FLAG_PIXELS_IRRELEVANT
|
|
11181
11173
|
};
|
|
11182
11174
|
if (layer.mask) {
|
|
11183
|
-
const m = maskChannel(layer.mask, 0, 0, psb);
|
|
11175
|
+
const m = maskChannel(layer.mask, 0, 0, psb, depth);
|
|
11184
11176
|
rec.channels.push(m.channel);
|
|
11185
11177
|
rec.mask = m.mask;
|
|
11186
11178
|
}
|
|
@@ -11192,11 +11184,11 @@ function exportPsd(input) {
|
|
|
11192
11184
|
const rec = {
|
|
11193
11185
|
...common2(layer, [{ key: block.key, data: block.data }]),
|
|
11194
11186
|
rect: EMPTY_RECT,
|
|
11195
|
-
channels: [CHANNEL_ALPHA,
|
|
11187
|
+
channels: [CHANNEL_ALPHA, ...colorIds].map(emptyChannel),
|
|
11196
11188
|
blendKey: BLEND_TO_PSD[layer.blend] ?? "norm"
|
|
11197
11189
|
};
|
|
11198
11190
|
if (layer.mask) {
|
|
11199
|
-
const m = maskChannel(layer.mask, 0, 0, psb);
|
|
11191
|
+
const m = maskChannel(layer.mask, 0, 0, psb, depth);
|
|
11200
11192
|
rec.channels.push(m.channel);
|
|
11201
11193
|
rec.mask = m.mask;
|
|
11202
11194
|
}
|
|
@@ -11213,20 +11205,13 @@ function exportPsd(input) {
|
|
|
11213
11205
|
const rec = { ...common2(layer, extra), rect: EMPTY_RECT, channels: [], blendKey: BLEND_TO_PSD[layer.blend] ?? "norm" };
|
|
11214
11206
|
const bounds = contentBounds(layer.surface);
|
|
11215
11207
|
if (bounds) {
|
|
11216
|
-
const n2 = bounds.width * bounds.height;
|
|
11217
|
-
const [r2, g2, b2, a2] = rgbaToPlanes(readRegion(layer.surface, bounds), n2);
|
|
11218
11208
|
rec.rect = toRect({ ...bounds, x: bounds.x + layer.offset.x, y: bounds.y + layer.offset.y });
|
|
11219
|
-
rec.channels =
|
|
11220
|
-
rleChannel(CHANNEL_ALPHA, a2, bounds.width, bounds.height, psb),
|
|
11221
|
-
rleChannel(0, r2, bounds.width, bounds.height, psb),
|
|
11222
|
-
rleChannel(1, g2, bounds.width, bounds.height, psb),
|
|
11223
|
-
rleChannel(2, b2, bounds.width, bounds.height, psb)
|
|
11224
|
-
];
|
|
11209
|
+
rec.channels = surfaceChannels(layer.surface, bounds);
|
|
11225
11210
|
} else {
|
|
11226
|
-
rec.channels = [CHANNEL_ALPHA,
|
|
11211
|
+
rec.channels = [CHANNEL_ALPHA, ...colorIds].map(emptyChannel);
|
|
11227
11212
|
}
|
|
11228
11213
|
if (layer.mask) {
|
|
11229
|
-
const m = maskChannel(layer.mask, layer.offset.x, layer.offset.y, psb);
|
|
11214
|
+
const m = maskChannel(layer.mask, layer.offset.x, layer.offset.y, psb, depth);
|
|
11230
11215
|
rec.channels.push(m.channel);
|
|
11231
11216
|
rec.mask = m.mask;
|
|
11232
11217
|
}
|
|
@@ -11264,20 +11249,13 @@ function exportPsd(input) {
|
|
|
11264
11249
|
const rec = { ...common2(layer, extra), rect: EMPTY_RECT, channels: [], blendKey: BLEND_TO_PSD[layer.blend] ?? "norm" };
|
|
11265
11250
|
const bounds = contentBounds(layer.surface);
|
|
11266
11251
|
if (bounds) {
|
|
11267
|
-
const n2 = bounds.width * bounds.height;
|
|
11268
|
-
const [r2, g2, b2, a2] = rgbaToPlanes(readRegion(layer.surface, bounds), n2);
|
|
11269
11252
|
rec.rect = toRect(bounds);
|
|
11270
|
-
rec.channels =
|
|
11271
|
-
rleChannel(CHANNEL_ALPHA, a2, bounds.width, bounds.height, psb),
|
|
11272
|
-
rleChannel(0, r2, bounds.width, bounds.height, psb),
|
|
11273
|
-
rleChannel(1, g2, bounds.width, bounds.height, psb),
|
|
11274
|
-
rleChannel(2, b2, bounds.width, bounds.height, psb)
|
|
11275
|
-
];
|
|
11253
|
+
rec.channels = surfaceChannels(layer.surface, bounds);
|
|
11276
11254
|
} else {
|
|
11277
|
-
rec.channels = [CHANNEL_ALPHA,
|
|
11255
|
+
rec.channels = [CHANNEL_ALPHA, ...colorIds].map(emptyChannel);
|
|
11278
11256
|
}
|
|
11279
11257
|
if (layer.mask) {
|
|
11280
|
-
const m = maskChannel(layer.mask, 0, 0, psb);
|
|
11258
|
+
const m = maskChannel(layer.mask, 0, 0, psb, depth);
|
|
11281
11259
|
rec.channels.push(m.channel);
|
|
11282
11260
|
rec.mask = m.mask;
|
|
11283
11261
|
}
|
|
@@ -11292,7 +11270,7 @@ function exportPsd(input) {
|
|
|
11292
11270
|
}
|
|
11293
11271
|
if (layer.type === "shape") {
|
|
11294
11272
|
const losses = /* @__PURE__ */ new Set();
|
|
11295
|
-
for (const
|
|
11273
|
+
for (const b of shapeBlocks(layer, width, height, input.resolution ?? 72, losses)) extra.push({ key: b.key, data: padEven(b.data) });
|
|
11296
11274
|
for (const n2 of losses) note(n2, layer.name);
|
|
11297
11275
|
if (layer.fill?.type === "pattern") patternIds2.add(layer.fill.patternId);
|
|
11298
11276
|
if (layer.stroke?.paint.type === "pattern") patternIds2.add(layer.stroke.paint.patternId);
|
|
@@ -11302,20 +11280,13 @@ function exportPsd(input) {
|
|
|
11302
11280
|
const rec = { ...common2(layer, extra), rect: EMPTY_RECT, channels: [], blendKey: BLEND_TO_PSD[layer.blend] ?? "norm" };
|
|
11303
11281
|
const bounds = contentBounds(layer.surface);
|
|
11304
11282
|
if (bounds) {
|
|
11305
|
-
const n2 = bounds.width * bounds.height;
|
|
11306
|
-
const [r2, g2, b2, a2] = rgbaToPlanes(readRegion(layer.surface, bounds), n2);
|
|
11307
11283
|
rec.rect = toRect(bounds);
|
|
11308
|
-
rec.channels =
|
|
11309
|
-
rleChannel(CHANNEL_ALPHA, a2, bounds.width, bounds.height, psb),
|
|
11310
|
-
rleChannel(0, r2, bounds.width, bounds.height, psb),
|
|
11311
|
-
rleChannel(1, g2, bounds.width, bounds.height, psb),
|
|
11312
|
-
rleChannel(2, b2, bounds.width, bounds.height, psb)
|
|
11313
|
-
];
|
|
11284
|
+
rec.channels = surfaceChannels(layer.surface, bounds);
|
|
11314
11285
|
} else {
|
|
11315
|
-
rec.channels = [CHANNEL_ALPHA,
|
|
11286
|
+
rec.channels = [CHANNEL_ALPHA, ...colorIds].map(emptyChannel);
|
|
11316
11287
|
}
|
|
11317
11288
|
if (layer.mask) {
|
|
11318
|
-
const m = maskChannel(layer.mask, 0, 0, psb);
|
|
11289
|
+
const m = maskChannel(layer.mask, 0, 0, psb, depth);
|
|
11319
11290
|
rec.channels.push(m.channel);
|
|
11320
11291
|
rec.mask = m.mask;
|
|
11321
11292
|
}
|
|
@@ -11330,11 +11301,18 @@ function exportPsd(input) {
|
|
|
11330
11301
|
if (records.length > 32767) throw new PsdError("A PSD holds at most 32767 layer records.");
|
|
11331
11302
|
const n = width * height;
|
|
11332
11303
|
if (input.merged.length < n * 4) throw new PsdError(`The merged image has ${input.merged.length} bytes, expected ${n * 4}.`);
|
|
11333
|
-
const
|
|
11304
|
+
const matted = matteWhite(input.merged);
|
|
11305
|
+
const a = rgbaToPlanes(matted, n)[3];
|
|
11334
11306
|
const transparent = a.some((v) => v !== 255);
|
|
11335
|
-
|
|
11336
|
-
const
|
|
11337
|
-
|
|
11307
|
+
let planes = [...colorPlanes(matted, n), ...transparent ? [a] : []].map((p) => planeAtDepth(p, depth));
|
|
11308
|
+
const deep = input.mergedDeep;
|
|
11309
|
+
if (deep && depth !== 8 && deep.length >= n * 4 && (deep instanceof Uint16Array ? depth === 16 : depth === 32)) {
|
|
11310
|
+
const dp = deepToPlanes(matteWhiteDeep(deep), n);
|
|
11311
|
+
planes = transparent ? dp : dp.slice(0, 3);
|
|
11312
|
+
}
|
|
11313
|
+
const planeBytes = n * (depth >> 3);
|
|
11314
|
+
const merged2 = new Uint8Array(planeBytes * planes.length);
|
|
11315
|
+
planes.forEach((p, i) => merged2.set(p, i * planeBytes));
|
|
11338
11316
|
const res = Math.max(1, input.resolution ?? 72);
|
|
11339
11317
|
const rw = new PsdWriter();
|
|
11340
11318
|
for (let k = 0; k < 2; k++) {
|
|
@@ -11352,6 +11330,7 @@ function exportPsd(input) {
|
|
|
11352
11330
|
{ id: 1005, name: "", data: rw.result() },
|
|
11353
11331
|
{ id: 1057, name: "", data: version.result() }
|
|
11354
11332
|
];
|
|
11333
|
+
if (input.iccProfile?.length) resources.push({ id: 1039, name: "", data: input.iccProfile });
|
|
11355
11334
|
if (input.globalLight) {
|
|
11356
11335
|
const i32 = (v) => {
|
|
11357
11336
|
const w = new PsdWriter();
|
|
@@ -11384,14 +11363,14 @@ function exportPsd(input) {
|
|
|
11384
11363
|
if (filterItems.length) globalBlocks.push({ key: "FEid", data: writeFilterEffects(filterItems) });
|
|
11385
11364
|
const bytes = writePsd(
|
|
11386
11365
|
{
|
|
11387
|
-
header: { psb, channels: planes.length, width, height, depth
|
|
11366
|
+
header: { psb, channels: planes.length, width, height, depth, colorMode: mode === "cmyk" ? 4 : mode === "lab" ? 9 : 3 },
|
|
11388
11367
|
colorModeData: new Uint8Array(0),
|
|
11389
11368
|
resources,
|
|
11390
11369
|
layers: records,
|
|
11391
11370
|
mergedAlpha: transparent && records.length > 0,
|
|
11392
11371
|
globalBlocks,
|
|
11393
|
-
imageCompression: 1,
|
|
11394
|
-
imageData: encodeRle(merged2, { planes: planes.length, width, height, depth
|
|
11372
|
+
imageCompression: depth === 32 ? 0 : 1,
|
|
11373
|
+
imageData: depth === 32 ? merged2 : encodeRle(merged2, { planes: planes.length, width, height, depth, psb })
|
|
11395
11374
|
},
|
|
11396
11375
|
encodeLegacyName
|
|
11397
11376
|
);
|
|
@@ -11527,6 +11506,7 @@ export {
|
|
|
11527
11506
|
activeAdjustmentLayers,
|
|
11528
11507
|
evaluateAdjustmentLayers,
|
|
11529
11508
|
applyAdjustmentLayers,
|
|
11509
|
+
applyAdjustmentLayersFloat,
|
|
11530
11510
|
adjustmentLayersKey,
|
|
11531
11511
|
applyAdjustments,
|
|
11532
11512
|
applyLegacyAdjustments,
|
|
@@ -11534,9 +11514,9 @@ export {
|
|
|
11534
11514
|
applyBoxBlur,
|
|
11535
11515
|
applyDepthMask,
|
|
11536
11516
|
removeAlpha,
|
|
11517
|
+
TEXT_ALIGNS,
|
|
11537
11518
|
SHAPE_OPERATIONS,
|
|
11538
11519
|
LIVE_SHAPE_KINDS,
|
|
11539
|
-
TEXT_ALIGNS,
|
|
11540
11520
|
newLayerId,
|
|
11541
11521
|
pixelLayers,
|
|
11542
11522
|
developFilter,
|
|
@@ -11553,6 +11533,7 @@ export {
|
|
|
11553
11533
|
depthMaskAlpha,
|
|
11554
11534
|
runLayerFilters,
|
|
11555
11535
|
LayerCompositor,
|
|
11536
|
+
compositeDeep,
|
|
11556
11537
|
DEFAULT_ADJUSTMENTS_VALUES,
|
|
11557
11538
|
DEFAULT_TRANSFORM_VALUES,
|
|
11558
11539
|
DEFAULT_DEPTH_MASK_VALUES,
|
|
@@ -11612,18 +11593,6 @@ export {
|
|
|
11612
11593
|
shapeFromAnnotation,
|
|
11613
11594
|
annotationBlend,
|
|
11614
11595
|
annotationOfShape,
|
|
11615
|
-
DEFAULT_TEXT_STYLE,
|
|
11616
|
-
DEFAULT_AUTO_LEADING,
|
|
11617
|
-
fitRuns,
|
|
11618
|
-
styleAt,
|
|
11619
|
-
restyleRange,
|
|
11620
|
-
spliceRuns,
|
|
11621
|
-
paragraphRanges,
|
|
11622
|
-
fitParagraphRuns,
|
|
11623
|
-
fontOf,
|
|
11624
|
-
layoutText,
|
|
11625
|
-
textIndexAt,
|
|
11626
|
-
caretAt,
|
|
11627
11596
|
TEXT_RENDER_MARGIN,
|
|
11628
11597
|
textMatrix,
|
|
11629
11598
|
textOutlines,
|
|
@@ -11725,6 +11694,8 @@ export {
|
|
|
11725
11694
|
serializePatterns,
|
|
11726
11695
|
deserializePatterns,
|
|
11727
11696
|
encodeSurface,
|
|
11697
|
+
encodeDeepSurface,
|
|
11698
|
+
decodeDeepSurface,
|
|
11728
11699
|
serializeEffects,
|
|
11729
11700
|
deserializeEffects,
|
|
11730
11701
|
serializeLayer,
|
|
@@ -11764,4 +11735,4 @@ export {
|
|
|
11764
11735
|
smartContentsFile,
|
|
11765
11736
|
exportPsd
|
|
11766
11737
|
};
|
|
11767
|
-
//# sourceMappingURL=chunk-
|
|
11738
|
+
//# sourceMappingURL=chunk-XICA4PVO.js.map
|