@pixerate/editor 0.113.0 → 0.114.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.
Files changed (124) hide show
  1. package/THIRD_PARTY_NOTICES.md +5 -0
  2. package/dist/animation-editor/index.cjs +60 -54
  3. package/dist/animation-editor/index.cjs.map +1 -1
  4. package/dist/animation-editor/index.d.cts +3 -3
  5. package/dist/animation-editor/index.d.ts +3 -3
  6. package/dist/animation-editor/index.js +14 -8
  7. package/dist/animation-editor/index.js.map +1 -1
  8. package/dist/builtin-CY97ppKM.d.cts +354 -0
  9. package/dist/builtin-CY97ppKM.d.ts +354 -0
  10. package/dist/canvas/index.cjs +3 -3
  11. package/dist/canvas/index.cjs.map +1 -1
  12. package/dist/canvas/index.js +9 -9
  13. package/dist/chunk-26PGXHY7.cjs +753 -0
  14. package/dist/chunk-26PGXHY7.cjs.map +1 -0
  15. package/dist/chunk-2OJACTPR.cjs +929 -0
  16. package/dist/chunk-2OJACTPR.cjs.map +1 -0
  17. package/dist/chunk-3UFGNHSP.js +929 -0
  18. package/dist/chunk-3UFGNHSP.js.map +1 -0
  19. package/dist/{chunk-YGIMK4NX.cjs → chunk-5OVJHMZQ.cjs} +757 -825
  20. package/dist/chunk-5OVJHMZQ.cjs.map +1 -0
  21. package/dist/chunk-643B2HKC.cjs +534 -0
  22. package/dist/chunk-643B2HKC.cjs.map +1 -0
  23. package/dist/chunk-6FCKOS2B.js +534 -0
  24. package/dist/chunk-6FCKOS2B.js.map +1 -0
  25. package/dist/chunk-BRLYOPLT.js +2574 -0
  26. package/dist/chunk-BRLYOPLT.js.map +1 -0
  27. package/dist/{chunk-LQEEDHOP.js → chunk-C6C5PDKU.js} +759 -761
  28. package/dist/chunk-C6C5PDKU.js.map +1 -0
  29. package/dist/{chunk-4KLT7ZYS.cjs → chunk-DFQEX3AM.cjs} +29 -29
  30. package/dist/{chunk-4KLT7ZYS.cjs.map → chunk-DFQEX3AM.cjs.map} +1 -1
  31. package/dist/{chunk-CZOXTEMN.js → chunk-EUVSQ25B.js} +336 -404
  32. package/dist/chunk-EUVSQ25B.js.map +1 -0
  33. package/dist/chunk-G5NMLUVF.cjs +2574 -0
  34. package/dist/chunk-G5NMLUVF.cjs.map +1 -0
  35. package/dist/{chunk-LPYOIVLA.js → chunk-LKCYANMW.js} +3 -3
  36. package/dist/{chunk-W3GXSUSQ.cjs → chunk-LPLCWZTM.cjs} +5087 -1283
  37. package/dist/chunk-LPLCWZTM.cjs.map +1 -0
  38. package/dist/chunk-MMVHBKMM.js +753 -0
  39. package/dist/chunk-MMVHBKMM.js.map +1 -0
  40. package/dist/{chunk-POGBUYWE.cjs → chunk-ST7E3NEE.cjs} +857 -859
  41. package/dist/chunk-ST7E3NEE.cjs.map +1 -0
  42. package/dist/{chunk-7VOHOPLW.cjs → chunk-TCKIXI46.cjs} +59 -59
  43. package/dist/{chunk-7VOHOPLW.cjs.map → chunk-TCKIXI46.cjs.map} +1 -1
  44. package/dist/{chunk-XIOMMGPD.cjs → chunk-TFOPHZ3U.cjs} +1 -1
  45. package/dist/chunk-TFOPHZ3U.cjs.map +1 -0
  46. package/dist/{chunk-Z4BC6M74.js → chunk-UBIXVXPR.js} +2 -2
  47. package/dist/{chunk-BLWCAQCW.js → chunk-VXR7XWMF.js} +4574 -770
  48. package/dist/chunk-VXR7XWMF.js.map +1 -0
  49. package/dist/{chunk-HNS7UHCM.js → chunk-XK5LZKBD.js} +1 -1
  50. package/dist/chunk-XK5LZKBD.js.map +1 -0
  51. package/dist/cms/index.cjs +146 -0
  52. package/dist/cms/index.cjs.map +1 -0
  53. package/dist/cms/index.d.cts +51 -0
  54. package/dist/cms/index.d.ts +51 -0
  55. package/dist/cms/index.js +146 -0
  56. package/dist/cms/index.js.map +1 -0
  57. package/dist/{export-DIkoK8-r.d.ts → export-_1dUKwpF.d.ts} +217 -191
  58. package/dist/{export-CEXEzqBf.d.cts → export-b6NjCZ5-.d.cts} +217 -191
  59. package/dist/image-editor/index.cjs +1779 -1280
  60. package/dist/image-editor/index.cjs.map +1 -1
  61. package/dist/image-editor/index.d.cts +77 -93
  62. package/dist/image-editor/index.d.ts +77 -93
  63. package/dist/image-editor/index.js +740 -241
  64. package/dist/image-editor/index.js.map +1 -1
  65. package/dist/opentype-BZEOSOX3.d.ts +188 -0
  66. package/dist/opentype-Dpe75vL5.d.cts +188 -0
  67. package/dist/paint/index.cjs +4 -4
  68. package/dist/paint/index.d.cts +2 -2
  69. package/dist/paint/index.d.ts +2 -2
  70. package/dist/paint/index.js +3 -3
  71. package/dist/paint-editor/index.cjs +146 -145
  72. package/dist/paint-editor/index.cjs.map +1 -1
  73. package/dist/paint-editor/index.d.cts +9 -8
  74. package/dist/paint-editor/index.d.ts +9 -8
  75. package/dist/paint-editor/index.js +6 -5
  76. package/dist/paint-editor/index.js.map +1 -1
  77. package/dist/raster/index.cjs +53 -3
  78. package/dist/raster/index.cjs.map +1 -1
  79. package/dist/raster/index.d.cts +62 -91
  80. package/dist/raster/index.d.ts +62 -91
  81. package/dist/raster/index.js +59 -9
  82. package/dist/{render-BEriFuqK.d.cts → render-B1K_OoLy.d.cts} +87 -2
  83. package/dist/{render-tjzKaik-.d.ts → render-CrmHOgpo.d.ts} +87 -2
  84. package/dist/{retouch-CEIKR22W.d.cts → retouch-Bxkuc0KH.d.cts} +1 -1
  85. package/dist/{retouch-BXmeSCaB.d.ts → retouch-Do6tBs2H.d.ts} +1 -1
  86. package/dist/{surface-C8RRg_Bh.d.cts → surface-Cn30xIV6.d.cts} +6 -1
  87. package/dist/{surface-C8RRg_Bh.d.ts → surface-Cn30xIV6.d.ts} +6 -1
  88. package/dist/{svg-D_cfkhlB.d.cts → svg-BnRj0q8i.d.cts} +16 -4
  89. package/dist/{svg-wIaKLrU0.d.ts → svg-CmmBFfGT.d.ts} +16 -4
  90. package/dist/{types-DtL_qLFz.d.ts → types-1SUQKDAw.d.ts} +273 -4
  91. package/dist/{types-DyQq-WPY.d.cts → types-yINF17Ta.d.cts} +273 -4
  92. package/dist/vector/index.cjs +12170 -7343
  93. package/dist/vector/index.cjs.map +1 -1
  94. package/dist/vector/index.d.cts +1579 -16
  95. package/dist/vector/index.d.ts +1579 -16
  96. package/dist/vector/index.js +6303 -1476
  97. package/dist/vector/index.js.map +1 -1
  98. package/dist/warp-B39VsOtd.d.cts +348 -0
  99. package/dist/warp-DMN30aY6.d.ts +348 -0
  100. package/dist/zlib-dxQdgHyN.d.cts +95 -0
  101. package/dist/zlib-dxQdgHyN.d.ts +95 -0
  102. package/package.json +6 -1
  103. package/skills/pixerate-image-editor/SKILL.md +12 -36
  104. package/skills/pixerate-image-editor/references/color-management.md +37 -0
  105. package/skills/pixerate-image-editor/references/photoshop-files.md +39 -0
  106. package/skills/pixerate-vector/SKILL.md +54 -2
  107. package/dist/chunk-BLWCAQCW.js.map +0 -1
  108. package/dist/chunk-CZOXTEMN.js.map +0 -1
  109. package/dist/chunk-HNS7UHCM.js.map +0 -1
  110. package/dist/chunk-JLYX4V57.cjs +0 -2001
  111. package/dist/chunk-JLYX4V57.cjs.map +0 -1
  112. package/dist/chunk-KB2YBCVS.js +0 -2001
  113. package/dist/chunk-KB2YBCVS.js.map +0 -1
  114. package/dist/chunk-LQEEDHOP.js.map +0 -1
  115. package/dist/chunk-POGBUYWE.cjs.map +0 -1
  116. package/dist/chunk-W3GXSUSQ.cjs.map +0 -1
  117. package/dist/chunk-XIOMMGPD.cjs.map +0 -1
  118. package/dist/chunk-YGIMK4NX.cjs.map +0 -1
  119. package/dist/homography-CZ-tFjay.d.cts +0 -50
  120. package/dist/homography-Ctfjoc1b.d.ts +0 -50
  121. package/dist/warp-CWHZzE3x.d.ts +0 -118
  122. package/dist/warp-D5jz_tN7.d.cts +0 -118
  123. /package/dist/{chunk-LPYOIVLA.js.map → chunk-LKCYANMW.js.map} +0 -0
  124. /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
- } from "./chunk-LQEEDHOP.js";
45
+ warpSurface,
46
+ writeDeepRegion
47
+ } from "./chunk-C6C5PDKU.js";
45
48
  import {
46
49
  affineFromHomography,
47
50
  applyHomography,
@@ -68,8 +71,15 @@ import {
68
71
  tileKey,
69
72
  tilesInRect,
70
73
  translateSurface
71
- } from "./chunk-HNS7UHCM.js";
74
+ } from "./chunk-XK5LZKBD.js";
75
+ import {
76
+ ZlibError,
77
+ deflate,
78
+ inflate
79
+ } from "./chunk-6FCKOS2B.js";
72
80
  import {
81
+ DEFAULT_AUTO_LEADING,
82
+ DEFAULT_TEXT_STYLE,
73
83
  IDENTITY_MATRIX,
74
84
  WARP_STYLES,
75
85
  applyMatrix,
@@ -77,11 +87,15 @@ import {
77
87
  ellipseSubpath,
78
88
  evalWarpMesh,
79
89
  expandVectorCorners,
90
+ fitParagraphRuns,
91
+ fitRuns,
80
92
  fitWarpMesh,
81
93
  identityWarpMesh,
82
94
  invertMatrix,
83
95
  isIdentityMatrix,
96
+ isTextSpace,
84
97
  isValidWarpMesh,
98
+ layoutText,
85
99
  mapWarpMeshPoints,
86
100
  matrixAbout,
87
101
  multiplyMatrices,
@@ -89,11 +103,16 @@ import {
89
103
  rectSubpath,
90
104
  rotateMatrix,
91
105
  setAnchorCorner,
106
+ spliceRuns,
92
107
  starSubpath,
108
+ styleAt,
93
109
  subpathsToBezier,
110
+ textDecorations,
111
+ textFragmentOutline,
112
+ textRectPath,
94
113
  translateMatrix,
95
114
  warpPresetMesh
96
- } from "./chunk-BLWCAQCW.js";
115
+ } from "./chunk-VXR7XWMF.js";
97
116
  import {
98
117
  bezierPathBounds,
99
118
  outlineStroke,
@@ -1742,7 +1761,7 @@ function lutOp(luts) {
1742
1761
  var isIdentityCurve = (pts) => pts.length === 2 && pts[0].input === 0 && pts[0].output === 0 && pts[1].input === 255 && pts[1].output === 255;
1743
1762
  var isIdentityLevels = (c) => c.inBlack === 0 && c.inWhite === 255 && c.gamma === 1 && c.outBlack === 0 && c.outWhite === 255;
1744
1763
  var LEVELS_QUANTUM = 255;
1745
- function toneLuts(layer) {
1764
+ function toneLuts(layer, quantum = LEVELS_QUANTUM) {
1746
1765
  const n = ADJUSTMENT_LUT_SIZE;
1747
1766
  if (layer.kind === "curves") {
1748
1767
  const m = curveLutFromLevels(layer.params.master);
@@ -1757,13 +1776,14 @@ function toneLuts(layer) {
1757
1776
  return [layer.params.red, layer.params.green, layer.params.blue].map((rec) => {
1758
1777
  const c = toUnitLevels(rec);
1759
1778
  const out = new Float32Array(n);
1760
- for (let k = 0; k < n; k++) out[k] = levelsValue(m, levelsValue(c, k / (n - 1), LEVELS_QUANTUM), LEVELS_QUANTUM);
1779
+ const q2 = quantum ?? void 0;
1780
+ for (let k = 0; k < n; k++) out[k] = levelsValue(m, levelsValue(c, k / (n - 1), q2), q2);
1761
1781
  return out;
1762
1782
  });
1763
1783
  }
1764
1784
  return null;
1765
1785
  }
1766
- function compileAdjustmentLayer(layer) {
1786
+ function compileAdjustmentLayer(layer, options = {}) {
1767
1787
  switch (layer.kind) {
1768
1788
  case "curves": {
1769
1789
  const p = layer.params;
@@ -1773,7 +1793,7 @@ function compileAdjustmentLayer(layer) {
1773
1793
  case "levels": {
1774
1794
  const p = layer.params;
1775
1795
  if ([p.master, p.red, p.green, p.blue].every(isIdentityLevels)) return null;
1776
- return lutOp(toneLuts(layer));
1796
+ return lutOp(toneLuts(layer, options.deep ? null : LEVELS_QUANTUM));
1777
1797
  }
1778
1798
  case "hueSaturation": {
1779
1799
  const p = layer.params;
@@ -1878,15 +1898,15 @@ function compileAdjustmentLayer(layer) {
1878
1898
  }
1879
1899
  var COMPILE_CACHE_LIMIT = 64;
1880
1900
  var compileCache = /* @__PURE__ */ new Map();
1881
- function compiledFor(layer) {
1882
- const key = `${layer.kind}:${JSON.stringify(layer.params)}`;
1901
+ function compiledFor(layer, deep = false) {
1902
+ const key = `${deep ? "deep:" : ""}${layer.kind}:${JSON.stringify(layer.params)}`;
1883
1903
  if (compileCache.has(key)) {
1884
1904
  const op2 = compileCache.get(key);
1885
1905
  compileCache.delete(key);
1886
1906
  compileCache.set(key, op2);
1887
1907
  return op2;
1888
1908
  }
1889
- const op = compileAdjustmentLayer(layer);
1909
+ const op = compileAdjustmentLayer(layer, { deep });
1890
1910
  compileCache.set(key, op);
1891
1911
  if (compileCache.size > COMPILE_CACHE_LIMIT) compileCache.delete(compileCache.keys().next().value);
1892
1912
  return op;
@@ -1947,6 +1967,29 @@ function applyAdjustmentLayers(imageData, layers, masks) {
1947
1967
  data[i + 2] = Math.round(clamp01(c[2]) * 255);
1948
1968
  }
1949
1969
  }
1970
+ function applyAdjustmentLayersFloat(data, layers, masks) {
1971
+ const active = activeAdjustmentLayers(layers);
1972
+ if (!active.length) return;
1973
+ const ops = active.map((l) => compiledFor(l, true));
1974
+ const planes = active.map((l) => masks?.get(l.id));
1975
+ const c = [0, 0, 0];
1976
+ for (let i = 0; i < data.length; i += 4) {
1977
+ if (!(data[i + 3] > 0)) continue;
1978
+ c[0] = data[i];
1979
+ c[1] = data[i + 1];
1980
+ c[2] = data[i + 2];
1981
+ for (let k = 0; k < active.length; k++) {
1982
+ const plane = planes[k];
1983
+ if (plane) {
1984
+ const cov = plane[i >> 2];
1985
+ if (cov > 0) applyLayer(c, active[k], ops[k], cov >= 1 ? 1 : cov);
1986
+ } else applyLayer(c, active[k], ops[k]);
1987
+ }
1988
+ data[i] = c[0];
1989
+ data[i + 1] = c[1];
1990
+ data[i + 2] = c[2];
1991
+ }
1992
+ }
1950
1993
  function adjustmentLayersKey(layers) {
1951
1994
  if (!layers?.length) return "";
1952
1995
  return JSON.stringify(
@@ -2222,10 +2265,12 @@ function removeAlpha(imageData) {
2222
2265
  }
2223
2266
  }
2224
2267
 
2268
+ // src/text/types.ts
2269
+ var TEXT_ALIGNS = ["left", "center", "right", "justify"];
2270
+
2225
2271
  // src/image-editor/layers/model.ts
2226
2272
  var SHAPE_OPERATIONS = ["combine", "subtract", "intersect", "exclude"];
2227
2273
  var LIVE_SHAPE_KINDS = ["rect", "ellipse", "polygon", "star", "line"];
2228
- var TEXT_ALIGNS = ["left", "center", "right", "justify"];
2229
2274
  var idCounter = 0;
2230
2275
  function newLayerId(prefix = "layer") {
2231
2276
  return `${prefix}_${Date.now().toString(36)}_${(++idCounter).toString(36)}`;
@@ -2376,6 +2421,12 @@ var LayerCompositor = class extends RasterCompositor {
2376
2421
  super(PHOTO_PROFILE, options);
2377
2422
  }
2378
2423
  };
2424
+ function compositeDeep(layers, rect, sources, depth) {
2425
+ const deep = new DeepCompositor(new LayerCompositor(), PHOTO_PROFILE, {
2426
+ applyFilterRunDeep: (run, acc, _r, masks) => applyAdjustmentLayersFloat(acc, run.map(adjustmentNodeAsLayer), masks)
2427
+ }, depth);
2428
+ return deep.composite(layers, rect, sources);
2429
+ }
2379
2430
 
2380
2431
  // src/image-editor/layers/vector-raster.ts
2381
2432
  var FLATNESS = 0.01;
@@ -3901,300 +3952,6 @@ function annotationOfShape(layer) {
3901
3952
  var fail3 = (message) => {
3902
3953
  throw new LayerOperationError(message);
3903
3954
  };
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
3955
  var TEXT_RENDER_MARGIN = MAX_EFFECT_REACH;
4199
3956
  function textMatrix(layer) {
4200
3957
  return layer.transform ?? IDENTITY_MATRIX;
@@ -4239,31 +3996,6 @@ function inkBounds(layout) {
4239
3996
  }
4240
3997
  return b;
4241
3998
  }
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
3999
  function textOutlines(layer, shaper) {
4268
4000
  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
4001
  const layout = layoutText(layer, shaper);
@@ -4271,8 +4003,8 @@ function textOutlines(layer, shaper) {
4271
4003
  const out = [];
4272
4004
  for (const l of layout.lines) {
4273
4005
  for (const f of l.fragments) {
4274
- let path = fragmentOutline(shaper, layer.text, f);
4275
- for (const r of decorations(f, l)) path = [...path, ...rectPath(r)];
4006
+ let path = textFragmentOutline(shaper, layer.text, f);
4007
+ for (const r of textDecorations(f, l)) path = [...path, ...textRectPath(r)];
4276
4008
  out.push({ fragment: f, path: isIdentityMatrix(m) ? path : transformBezierPath(path, m) });
4277
4009
  }
4278
4010
  }
@@ -4341,8 +4073,8 @@ function renderOnCanvas(layer, shaper, region, env) {
4341
4073
  ctx.globalAlpha = f.style.opacity ?? 1;
4342
4074
  const s = layer.text.slice(f.start, f.end);
4343
4075
  if (!f.spaced) shaper.draw(ctx, s, f.font, f.x, f.y);
4344
- else for (let k = 0; k < s.length; k++) if (!isSpace(s[k])) shaper.draw(ctx, s[k], f.font, f.x + f.carets[k], f.y);
4345
- for (const d of decorations(f, l)) ctx.fillRect(d.x, d.y, d.width, d.height);
4076
+ 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);
4077
+ for (const d of textDecorations(f, l)) ctx.fillRect(d.x, d.y, d.width, d.height);
4346
4078
  }
4347
4079
  }
4348
4080
  ctx.globalAlpha = 1;
@@ -5679,6 +5411,42 @@ function encodeSurface(surface) {
5679
5411
  encodedCache.set(surface, out);
5680
5412
  return out;
5681
5413
  }
5414
+ var deepCache = /* @__PURE__ */ new WeakMap();
5415
+ function encodeDeepSurface(surface) {
5416
+ if (deepCache.has(surface)) return deepCache.get(surface);
5417
+ let out = null;
5418
+ const depth = surfaceDepth(surface);
5419
+ const b = depth === 8 ? null : contentBounds(surface);
5420
+ if (depth !== 8 && b) {
5421
+ const samples = readDeepRegion(surface, b, depth);
5422
+ const bytes = new Uint8Array(samples.byteLength);
5423
+ const view = new DataView(bytes.buffer);
5424
+ if (samples instanceof Uint16Array) for (let i = 0; i < samples.length; i++) view.setUint16(2 * i, samples[i], true);
5425
+ else for (let i = 0; i < samples.length; i++) view.setFloat32(4 * i, samples[i], true);
5426
+ out = { depth, x: b.x, y: b.y, width: b.width, height: b.height, data: bytesToBase64(deflate(bytes)) };
5427
+ }
5428
+ deepCache.set(surface, out);
5429
+ return out;
5430
+ }
5431
+ function decodeDeepSurface(surface, raw, problems, label) {
5432
+ const d = raw;
5433
+ if (!d || typeof d !== "object") return surface;
5434
+ try {
5435
+ 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");
5436
+ const n = d.width * d.height * 4;
5437
+ const size = d.depth === 16 ? 2 : 4;
5438
+ const bytes = inflate(base64ToBytes(d.data), { maxOutput: n * size });
5439
+ if (bytes.length !== n * size) throw new Error("wrong length");
5440
+ const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
5441
+ const samples = d.depth === 16 ? new Uint16Array(n) : new Float32Array(n);
5442
+ if (samples instanceof Uint16Array) for (let i = 0; i < n; i++) samples[i] = view.getUint16(2 * i, true);
5443
+ else for (let i = 0; i < n; i++) samples[i] = view.getFloat32(4 * i, true);
5444
+ return writeDeepRegion(surface, { x: d.x, y: d.y, width: d.width, height: d.height }, samples);
5445
+ } catch {
5446
+ problems.push(`${label}: its ${d.depth}-bit samples could not be read, so it was opened at 8 bits`);
5447
+ return surface;
5448
+ }
5449
+ }
5682
5450
  function baseFields(layer, ctx) {
5683
5451
  const out = {
5684
5452
  id: layer.id,
@@ -5747,6 +5515,10 @@ function serializeLayer(layer, ctx) {
5747
5515
  }
5748
5516
  if (layer.fillOpacity !== void 0 && layer.fillOpacity !== 1) out.fillOpacity = layer.fillOpacity;
5749
5517
  if (layer.filters?.length) out.filters = JSON.parse(JSON.stringify(layer.filters));
5518
+ if (layer.source !== "document") {
5519
+ const deep = encodeDeepSurface(layer.surface);
5520
+ if (deep) out.deep = deep;
5521
+ }
5750
5522
  return out;
5751
5523
  }
5752
5524
  case "adjustment":
@@ -6128,6 +5900,7 @@ function deserializeLayer(raw, ctx) {
6128
5900
  offset: { x: Math.round(num2(r.offset?.x, -1e7, 1e7, 0)), y: Math.round(num2(r.offset?.y, -1e7, 1e7, 0)) }
6129
5901
  };
6130
5902
  if (r.source === "document") layer.source = "document";
5903
+ else if (r.deep) layer.surface = decodeDeepSurface(layer.surface, r.deep, ctx.problems, `Layer "${base.name || id}"`);
6131
5904
  if (typeof r.fillOpacity === "number" && r.fillOpacity !== 1) layer.fillOpacity = num2(r.fillOpacity, 0, 1, 1);
6132
5905
  const filters = readFilters(r.filters);
6133
5906
  if (filters) layer.filters = filters;
@@ -8465,6 +8238,36 @@ function encodeRle(decoded2, l) {
8465
8238
  out.set(packed.subarray(0, at), counts.length);
8466
8239
  return out;
8467
8240
  }
8241
+ function predict(buf, l) {
8242
+ const rb = rowBytes(l.width, l.depth);
8243
+ if (rb === 0) return;
8244
+ const w = l.width;
8245
+ const scratch = l.depth === 32 ? new Uint8Array(rb) : null;
8246
+ for (let o = 0; o + rb <= buf.length; o += rb) {
8247
+ if (l.depth === 1 || l.depth === 8) {
8248
+ for (let i = rb - 1; i > 0; i--) buf[o + i] = buf[o + i] - buf[o + i - 1] & 255;
8249
+ } else if (l.depth === 16) {
8250
+ for (let i = w - 1; i > 0; i--) {
8251
+ const a = buf[o + 2 * i] << 8 | buf[o + 2 * i + 1];
8252
+ const b = buf[o + 2 * i - 2] << 8 | buf[o + 2 * i - 1];
8253
+ const v = a - b & 65535;
8254
+ buf[o + 2 * i] = v >> 8;
8255
+ buf[o + 2 * i + 1] = v & 255;
8256
+ }
8257
+ } else if (l.depth === 32) {
8258
+ scratch.set(buf.subarray(o, o + rb));
8259
+ for (let i = 0; i < w; i++) for (let k = 0; k < 4; k++) buf[o + k * w + i] = scratch[4 * i + k];
8260
+ for (let i = rb - 1; i > 0; i--) buf[o + i] = buf[o + i] - buf[o + i - 1] & 255;
8261
+ } else {
8262
+ throw new PsdError(`ZIP prediction is not defined for depth ${l.depth}.`);
8263
+ }
8264
+ }
8265
+ }
8266
+ function encodeZipPredicted(decoded2, l) {
8267
+ const buf = decoded2.slice();
8268
+ predict(buf, l);
8269
+ return deflate(buf);
8270
+ }
8468
8271
 
8469
8272
  // src/image-editor/psd/smart.ts
8470
8273
  var dbl2 = (value) => ({ type: "doub", value });
@@ -9405,23 +9208,31 @@ function writePsd(file, encodeName) {
9405
9208
  w.endLen(res);
9406
9209
  const lm = w.beginLen(psb);
9407
9210
  if (file.layers.length || file.globalBlocks.length) {
9408
- const li = w.beginLen(psb);
9409
- if (file.layers.length) {
9410
- const start = w.length;
9411
- w.i16(file.mergedAlpha ? -file.layers.length : file.layers.length);
9412
- for (const rec of file.layers) writeLayerRecord(w, rec, psb, encodeName(rec.legacyName));
9211
+ const writeLayerInfo = (out) => {
9212
+ const start = out.length;
9213
+ out.i16(file.mergedAlpha ? -file.layers.length : file.layers.length);
9214
+ for (const rec of file.layers) writeLayerRecord(out, rec, psb, encodeName(rec.legacyName));
9413
9215
  for (const rec of file.layers) {
9414
9216
  for (const c of rec.channels) {
9415
9217
  if (c.compression === null) continue;
9416
- w.u16(c.compression);
9417
- w.bytes(c.data);
9218
+ out.u16(c.compression);
9219
+ out.bytes(c.data);
9418
9220
  }
9419
9221
  }
9420
- if ((w.length - start) % 2) w.u8(0);
9421
- }
9222
+ if ((out.length - start) % 2) out.u8(0);
9223
+ };
9224
+ const deepKey = header.depth === 16 ? "Lr16" : header.depth === 32 ? "Lr32" : null;
9225
+ let blocks = file.globalBlocks;
9226
+ const li = w.beginLen(psb);
9227
+ if (file.layers.length && !deepKey) writeLayerInfo(w);
9422
9228
  w.endLen(li);
9229
+ if (file.layers.length && deepKey) {
9230
+ const lw = new PsdWriter();
9231
+ writeLayerInfo(lw);
9232
+ blocks = [{ key: deepKey, data: lw.result() }, ...blocks];
9233
+ }
9423
9234
  w.u32(0);
9424
- writeBlocks(w, file.globalBlocks, psb, 4);
9235
+ writeBlocks(w, blocks, psb, 4);
9425
9236
  }
9426
9237
  w.endLen(lm);
9427
9238
  w.u16(file.imageCompression);
@@ -9430,6 +9241,7 @@ function writePsd(file, encodeName) {
9430
9241
  }
9431
9242
 
9432
9243
  // src/image-editor/psd/pixels.ts
9244
+ var MODE_BITMAP = 0;
9433
9245
  var MODE_INDEXED = 2;
9434
9246
  var MODE_RGB = 3;
9435
9247
  var MODE_CMYK = 4;
@@ -9553,6 +9365,99 @@ function toRgba8(set) {
9553
9365
  }
9554
9366
  return out;
9555
9367
  }
9368
+ function toRgbaDeep(set) {
9369
+ const { width, height, depth, mode } = set;
9370
+ if (depth !== 16 && depth !== 32 || mode === MODE_INDEXED || mode === MODE_BITMAP) return null;
9371
+ const n = width * height;
9372
+ const isLab = mode === MODE_LAB;
9373
+ const cmyk = mode === MODE_CMYK;
9374
+ const raw = (plane, fill) => {
9375
+ if (!plane) return () => fill;
9376
+ if (depth === 16) return (i) => (plane[2 * i] << 8 | plane[2 * i + 1]) / 65535;
9377
+ const view = new DataView(plane.buffer, plane.byteOffset, plane.byteLength);
9378
+ return (i) => view.getFloat32(4 * i, false) || 0;
9379
+ };
9380
+ const planes = set.color.map((p) => raw(p, cmyk ? 1 : 0));
9381
+ const alpha = raw(set.alpha, 1);
9382
+ if (depth === 16) {
9383
+ const out2 = new Uint16Array(n * 4);
9384
+ const q2 = (v) => Math.round(clamp012(v) * 65535);
9385
+ for (let i = 0, o = 0; i < n; i++, o += 4) {
9386
+ let r;
9387
+ let g;
9388
+ let b;
9389
+ if (mode === MODE_CMYK) {
9390
+ const k = planes[3] ? planes[3](i) : 1;
9391
+ r = planes[0](i) * k;
9392
+ g = planes[1](i) * k;
9393
+ b = planes[2](i) * k;
9394
+ } else if (isLab) {
9395
+ [r, g, b] = labToSrgb(planes[0](i) * 100, planes[1](i) * 255 - 128, planes[2](i) * 255 - 128);
9396
+ } else if (mode === MODE_RGB || mode === MODE_MULTICHANNEL) {
9397
+ r = planes[0](i);
9398
+ g = planes[1] ? planes[1](i) : r;
9399
+ b = planes[2] ? planes[2](i) : r;
9400
+ } else r = g = b = planes[0](i);
9401
+ out2[o] = q2(r);
9402
+ out2[o + 1] = q2(g);
9403
+ out2[o + 2] = q2(b);
9404
+ out2[o + 3] = q2(alpha(i));
9405
+ }
9406
+ return out2;
9407
+ }
9408
+ const out = new Float32Array(n * 4);
9409
+ for (let i = 0, o = 0; i < n; i++, o += 4) {
9410
+ let r;
9411
+ let g;
9412
+ let b;
9413
+ if (isLab) {
9414
+ [r, g, b] = labToSrgb(planes[0](i) * 100, planes[1](i) * 255 - 128, planes[2](i) * 255 - 128).map(srgbToLinear);
9415
+ } else if (cmyk) {
9416
+ const k = planes[3] ? planes[3](i) : 1;
9417
+ r = planes[0](i) * k;
9418
+ g = planes[1](i) * k;
9419
+ b = planes[2](i) * k;
9420
+ } else if (mode === MODE_RGB || mode === MODE_MULTICHANNEL) {
9421
+ r = planes[0](i);
9422
+ g = planes[1] ? planes[1](i) : r;
9423
+ b = planes[2] ? planes[2](i) : r;
9424
+ } else r = g = b = planes[0](i);
9425
+ out[o] = r;
9426
+ out[o + 1] = g;
9427
+ out[o + 2] = b;
9428
+ out[o + 3] = clamp012(alpha(i));
9429
+ }
9430
+ return out;
9431
+ }
9432
+ function deepToPlanes(data, n) {
9433
+ const bytes = data instanceof Uint16Array ? 2 : 4;
9434
+ const planes = [0, 1, 2, 3].map(() => new Uint8Array(n * bytes));
9435
+ if (data instanceof Uint16Array) {
9436
+ for (let i = 0; i < n; i++) {
9437
+ for (let c = 0; c < 4; c++) {
9438
+ const v = data[i * 4 + c];
9439
+ planes[c][2 * i] = v >> 8;
9440
+ planes[c][2 * i + 1] = v & 255;
9441
+ }
9442
+ }
9443
+ } else {
9444
+ const views = planes.map((p) => new DataView(p.buffer));
9445
+ for (let i = 0; i < n; i++) for (let c = 0; c < 4; c++) views[c].setFloat32(4 * i, data[i * 4 + c], false);
9446
+ }
9447
+ return planes;
9448
+ }
9449
+ function planeAtDepth(plane, depth) {
9450
+ if (depth === 8) return plane;
9451
+ if (depth === 16) {
9452
+ const out2 = new Uint8Array(plane.length * 2);
9453
+ for (let i = 0; i < plane.length; i++) out2[2 * i] = out2[2 * i + 1] = plane[i];
9454
+ return out2;
9455
+ }
9456
+ const out = new Uint8Array(plane.length * 4);
9457
+ const view = new DataView(out.buffer);
9458
+ for (let i = 0; i < plane.length; i++) view.setFloat32(4 * i, plane[i] / 255, false);
9459
+ return out;
9460
+ }
9556
9461
  function toMask8(plane, width, height, depth) {
9557
9462
  if (depth === 8) return new Uint8ClampedArray(plane.buffer, plane.byteOffset, width * height);
9558
9463
  const s = sampler(plane, depth, width, false, 0);
@@ -9587,6 +9492,16 @@ function matteWhite(data) {
9587
9492
  }
9588
9493
  return out;
9589
9494
  }
9495
+ function matteWhiteDeep(data) {
9496
+ const out = data.slice();
9497
+ const one = out instanceof Uint16Array ? 65535 : 1;
9498
+ for (let i = 0; i < out.length; i += 4) {
9499
+ const a = Math.min(1, Math.max(0, out[i + 3] / one));
9500
+ if (a >= 1) continue;
9501
+ 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);
9502
+ }
9503
+ return out;
9504
+ }
9590
9505
 
9591
9506
  // src/image-editor/psd/patterns.ts
9592
9507
  var MAX_EDGE = 3e4;
@@ -9823,7 +9738,7 @@ function recordPixels(ctx, rec, name) {
9823
9738
  const planes = ids.map((id) => rec.channels.some((c) => c.id === id) ? decodeOr(ctx, rec, id, name) ?? null : void 0);
9824
9739
  if (planes.some((p) => p === null)) return emptySurface(4);
9825
9740
  if (planes.every((p) => p === void 0)) return emptySurface(4);
9826
- const data = toRgba8({
9741
+ const set = {
9827
9742
  width,
9828
9743
  height,
9829
9744
  depth: ctx.file.header.depth,
@@ -9831,8 +9746,10 @@ function recordPixels(ctx, rec, name) {
9831
9746
  color: planes.slice(0, ctx.colorCount),
9832
9747
  alpha: planes[ctx.colorCount],
9833
9748
  palette: ctx.palette
9834
- });
9835
- return surfaceFromPixels({ width, height, data }, 4, rec.rect.left, rec.rect.top);
9749
+ };
9750
+ const deep = toRgbaDeep(set);
9751
+ if (deep) return surfaceFromDeepPixels({ width, height, data: deep }, 4, rec.rect.left, rec.rect.top);
9752
+ return surfaceFromPixels({ width, height, data: toRgba8(set) }, 4, rec.rect.left, rec.rect.top);
9836
9753
  }
9837
9754
  function recordMask(ctx, rec, name) {
9838
9755
  const m = rec.mask;
@@ -10230,7 +10147,7 @@ function mergedLayer(ctx) {
10230
10147
  const plane = (i) => i < header.channels ? planes.subarray(i * size, (i + 1) * size) : void 0;
10231
10148
  const cc = ctx.colorCount;
10232
10149
  const hasAlpha = header.channels > cc && (ctx.file.layers.length === 0 || ctx.file.mergedAlpha);
10233
- const data = toRgba8({
10150
+ const set = {
10234
10151
  width,
10235
10152
  height,
10236
10153
  depth: header.depth,
@@ -10238,8 +10155,15 @@ function mergedLayer(ctx) {
10238
10155
  color: Array.from({ length: cc }, (_, i) => plane(i)),
10239
10156
  alpha: hasAlpha ? plane(cc) : void 0,
10240
10157
  palette: ctx.palette
10241
- });
10242
- if (hasAlpha) unmatteWhite(data);
10158
+ };
10159
+ const deep = hasAlpha ? null : toRgbaDeep(set);
10160
+ let surface;
10161
+ if (deep) surface = surfaceFromDeepPixels({ width, height, data: deep }, 4);
10162
+ else {
10163
+ const data = toRgba8(set);
10164
+ if (hasAlpha) unmatteWhite(data);
10165
+ surface = surfaceFromPixels({ width, height, data }, 4);
10166
+ }
10243
10167
  return {
10244
10168
  type: "pixel",
10245
10169
  id: ctx.newId("Background"),
@@ -10247,7 +10171,7 @@ function mergedLayer(ctx) {
10247
10171
  visible: true,
10248
10172
  opacity: 1,
10249
10173
  blend: "normal",
10250
- surface: surfaceFromPixels({ width, height, data }, 4),
10174
+ surface,
10251
10175
  offset: { x: 0, y: 0 }
10252
10176
  };
10253
10177
  }
@@ -10291,10 +10215,11 @@ function psdToLayers(file, options = {}) {
10291
10215
  }
10292
10216
  }
10293
10217
  const mode = COLOR_MODES[header.colorMode] ?? `mode ${header.colorMode}`;
10294
- if (mode !== "rgb" || header.depth !== 8) {
10218
+ if (mode !== "rgb" && header.depth > 8 && header.colorMode !== MODE_INDEXED && header.colorMode !== MODE_BITMAP) {
10219
+ warn.extra.push(`The file is ${header.depth}-bit ${mode}; it was converted to ${header.depth}-bit RGB.`);
10220
+ } else if (mode !== "rgb" || header.depth !== 8 && header.depth !== 16 && header.depth !== 32) {
10295
10221
  warn.extra.push(`The file is ${header.depth}-bit ${mode}; it was converted to 8-bit RGB.`);
10296
10222
  }
10297
- if (resource(file, 1039)) warn.extra.push("The embedded ICC profile is ignored; colours are read as sRGB.");
10298
10223
  let layers = [];
10299
10224
  if (file.layers.length) {
10300
10225
  const tree = layerTree(file);
@@ -10327,7 +10252,9 @@ function psdToLayers(file, options = {}) {
10327
10252
  resolution: resolution(file),
10328
10253
  patterns: [...ctx.patterns.values()],
10329
10254
  ...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 }
10255
+ info: { psb: header.psb, depth: header.depth, colorMode: mode, channels: header.channels },
10256
+ ...resource(file, 1039) ? { iccProfile: resource(file, 1039).slice() } : {},
10257
+ bitDepth: (header.depth === 16 || header.depth === 32) && header.colorMode !== MODE_INDEXED && header.colorMode !== MODE_BITMAP ? header.depth : 8
10331
10258
  };
10332
10259
  }
10333
10260
  function importPsd(bytes, options = {}) {
@@ -11020,11 +10947,18 @@ function sectionBlock(kind, blendKey) {
11020
10947
  return w.result();
11021
10948
  }
11022
10949
  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
- return { id, compression: 1, data: encodeRle(plane, { planes: 1, width, height, depth: 8, psb }) };
10950
+ function rleChannel(id, plane, width, height, psb, depth = 8) {
10951
+ const layout = { planes: 1, width, height, depth, psb };
10952
+ if (depth === 32) return { id, compression: 3, data: encodeZipPredicted(plane, layout) };
10953
+ return { id, compression: 1, data: encodeRle(plane, layout) };
10954
+ }
10955
+ function surfacePlanes(surface, bounds, depth) {
10956
+ const n = bounds.width * bounds.height;
10957
+ if (depth === 8) return rgbaToPlanes(readRegion(surface, bounds), n);
10958
+ return deepToPlanes(readDeepRegion(surface, bounds, depth), n);
11025
10959
  }
11026
10960
  var emptyChannel = (id) => ({ id, compression: 0, data: new Uint8Array(0) });
11027
- function maskChannel(mask, ox, oy, psb) {
10961
+ function maskChannel(mask, ox, oy, psb, depth = 8) {
11028
10962
  if (mask.source) throw new PsdError("A parametric mask must be baked before export.");
11029
10963
  const bounds = contentBounds(mask.surface);
11030
10964
  const def = mask.defaultValue;
@@ -11035,7 +10969,8 @@ function maskChannel(mask, ox, oy, psb) {
11035
10969
  if (!bounds) return { channel: emptyChannel(CHANNEL_USER_MASK), mask: m };
11036
10970
  const plane = readRegion(mask.surface, bounds);
11037
10971
  m.rect = toRect({ ...bounds, x: bounds.x + ox, y: bounds.y + oy });
11038
- return { channel: rleChannel(CHANNEL_USER_MASK, new Uint8Array(plane.buffer, plane.byteOffset, plane.length), bounds.width, bounds.height, psb), mask: m };
10972
+ const bytes = planeAtDepth(new Uint8Array(plane.buffer, plane.byteOffset, plane.length), depth);
10973
+ return { channel: rleChannel(CHANNEL_USER_MASK, bytes, bounds.width, bounds.height, psb, depth), mask: m };
11039
10974
  }
11040
10975
  function lockBits(layer) {
11041
10976
  const l = layer.locks;
@@ -11114,6 +11049,7 @@ function placedUnchanged(layer, idnt, placedId) {
11114
11049
  }
11115
11050
  function exportPsd(input) {
11116
11051
  const { width, height } = input;
11052
+ const depth = input.depth ?? 8;
11117
11053
  if (width < 1 || height < 1) throw new PsdError("The document is empty.");
11118
11054
  const psb = width > PSD_MAX_DIMENSION || height > PSD_MAX_DIMENSION;
11119
11055
  const records = [];
@@ -11180,7 +11116,7 @@ function exportPsd(input) {
11180
11116
  flags: base.flags | FLAG_PIXELS_IRRELEVANT
11181
11117
  };
11182
11118
  if (layer.mask) {
11183
- const m = maskChannel(layer.mask, 0, 0, psb);
11119
+ const m = maskChannel(layer.mask, 0, 0, psb, depth);
11184
11120
  rec.channels.push(m.channel);
11185
11121
  rec.mask = m.mask;
11186
11122
  }
@@ -11196,7 +11132,7 @@ function exportPsd(input) {
11196
11132
  blendKey: BLEND_TO_PSD[layer.blend] ?? "norm"
11197
11133
  };
11198
11134
  if (layer.mask) {
11199
- const m = maskChannel(layer.mask, 0, 0, psb);
11135
+ const m = maskChannel(layer.mask, 0, 0, psb, depth);
11200
11136
  rec.channels.push(m.channel);
11201
11137
  rec.mask = m.mask;
11202
11138
  }
@@ -11213,20 +11149,19 @@ function exportPsd(input) {
11213
11149
  const rec = { ...common2(layer, extra), rect: EMPTY_RECT, channels: [], blendKey: BLEND_TO_PSD[layer.blend] ?? "norm" };
11214
11150
  const bounds = contentBounds(layer.surface);
11215
11151
  if (bounds) {
11216
- const n2 = bounds.width * bounds.height;
11217
- const [r2, g2, b2, a2] = rgbaToPlanes(readRegion(layer.surface, bounds), n2);
11152
+ const [r2, g2, b2, a2] = surfacePlanes(layer.surface, bounds, depth);
11218
11153
  rec.rect = toRect({ ...bounds, x: bounds.x + layer.offset.x, y: bounds.y + layer.offset.y });
11219
11154
  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)
11155
+ rleChannel(CHANNEL_ALPHA, a2, bounds.width, bounds.height, psb, depth),
11156
+ rleChannel(0, r2, bounds.width, bounds.height, psb, depth),
11157
+ rleChannel(1, g2, bounds.width, bounds.height, psb, depth),
11158
+ rleChannel(2, b2, bounds.width, bounds.height, psb, depth)
11224
11159
  ];
11225
11160
  } else {
11226
11161
  rec.channels = [CHANNEL_ALPHA, 0, 1, 2].map(emptyChannel);
11227
11162
  }
11228
11163
  if (layer.mask) {
11229
- const m = maskChannel(layer.mask, layer.offset.x, layer.offset.y, psb);
11164
+ const m = maskChannel(layer.mask, layer.offset.x, layer.offset.y, psb, depth);
11230
11165
  rec.channels.push(m.channel);
11231
11166
  rec.mask = m.mask;
11232
11167
  }
@@ -11264,20 +11199,19 @@ function exportPsd(input) {
11264
11199
  const rec = { ...common2(layer, extra), rect: EMPTY_RECT, channels: [], blendKey: BLEND_TO_PSD[layer.blend] ?? "norm" };
11265
11200
  const bounds = contentBounds(layer.surface);
11266
11201
  if (bounds) {
11267
- const n2 = bounds.width * bounds.height;
11268
- const [r2, g2, b2, a2] = rgbaToPlanes(readRegion(layer.surface, bounds), n2);
11202
+ const [r2, g2, b2, a2] = surfacePlanes(layer.surface, bounds, depth);
11269
11203
  rec.rect = toRect(bounds);
11270
11204
  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)
11205
+ rleChannel(CHANNEL_ALPHA, a2, bounds.width, bounds.height, psb, depth),
11206
+ rleChannel(0, r2, bounds.width, bounds.height, psb, depth),
11207
+ rleChannel(1, g2, bounds.width, bounds.height, psb, depth),
11208
+ rleChannel(2, b2, bounds.width, bounds.height, psb, depth)
11275
11209
  ];
11276
11210
  } else {
11277
11211
  rec.channels = [CHANNEL_ALPHA, 0, 1, 2].map(emptyChannel);
11278
11212
  }
11279
11213
  if (layer.mask) {
11280
- const m = maskChannel(layer.mask, 0, 0, psb);
11214
+ const m = maskChannel(layer.mask, 0, 0, psb, depth);
11281
11215
  rec.channels.push(m.channel);
11282
11216
  rec.mask = m.mask;
11283
11217
  }
@@ -11302,20 +11236,19 @@ function exportPsd(input) {
11302
11236
  const rec = { ...common2(layer, extra), rect: EMPTY_RECT, channels: [], blendKey: BLEND_TO_PSD[layer.blend] ?? "norm" };
11303
11237
  const bounds = contentBounds(layer.surface);
11304
11238
  if (bounds) {
11305
- const n2 = bounds.width * bounds.height;
11306
- const [r2, g2, b2, a2] = rgbaToPlanes(readRegion(layer.surface, bounds), n2);
11239
+ const [r2, g2, b2, a2] = surfacePlanes(layer.surface, bounds, depth);
11307
11240
  rec.rect = toRect(bounds);
11308
11241
  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)
11242
+ rleChannel(CHANNEL_ALPHA, a2, bounds.width, bounds.height, psb, depth),
11243
+ rleChannel(0, r2, bounds.width, bounds.height, psb, depth),
11244
+ rleChannel(1, g2, bounds.width, bounds.height, psb, depth),
11245
+ rleChannel(2, b2, bounds.width, bounds.height, psb, depth)
11313
11246
  ];
11314
11247
  } else {
11315
11248
  rec.channels = [CHANNEL_ALPHA, 0, 1, 2].map(emptyChannel);
11316
11249
  }
11317
11250
  if (layer.mask) {
11318
- const m = maskChannel(layer.mask, 0, 0, psb);
11251
+ const m = maskChannel(layer.mask, 0, 0, psb, depth);
11319
11252
  rec.channels.push(m.channel);
11320
11253
  rec.mask = m.mask;
11321
11254
  }
@@ -11332,9 +11265,15 @@ function exportPsd(input) {
11332
11265
  if (input.merged.length < n * 4) throw new PsdError(`The merged image has ${input.merged.length} bytes, expected ${n * 4}.`);
11333
11266
  const [r, g, b, a] = rgbaToPlanes(matteWhite(input.merged), n);
11334
11267
  const transparent = a.some((v) => v !== 255);
11335
- const planes = transparent ? [r, g, b, a] : [r, g, b];
11336
- const merged2 = new Uint8Array(n * planes.length);
11337
- planes.forEach((p, i) => merged2.set(p, i * n));
11268
+ let planes = (transparent ? [r, g, b, a] : [r, g, b]).map((p) => planeAtDepth(p, depth));
11269
+ const deep = input.mergedDeep;
11270
+ if (deep && depth !== 8 && deep.length >= n * 4 && (deep instanceof Uint16Array ? depth === 16 : depth === 32)) {
11271
+ const dp = deepToPlanes(matteWhiteDeep(deep), n);
11272
+ planes = transparent ? dp : dp.slice(0, 3);
11273
+ }
11274
+ const planeBytes = n * (depth >> 3);
11275
+ const merged2 = new Uint8Array(planeBytes * planes.length);
11276
+ planes.forEach((p, i) => merged2.set(p, i * planeBytes));
11338
11277
  const res = Math.max(1, input.resolution ?? 72);
11339
11278
  const rw = new PsdWriter();
11340
11279
  for (let k = 0; k < 2; k++) {
@@ -11352,6 +11291,7 @@ function exportPsd(input) {
11352
11291
  { id: 1005, name: "", data: rw.result() },
11353
11292
  { id: 1057, name: "", data: version.result() }
11354
11293
  ];
11294
+ if (input.iccProfile?.length) resources.push({ id: 1039, name: "", data: input.iccProfile });
11355
11295
  if (input.globalLight) {
11356
11296
  const i32 = (v) => {
11357
11297
  const w = new PsdWriter();
@@ -11384,14 +11324,14 @@ function exportPsd(input) {
11384
11324
  if (filterItems.length) globalBlocks.push({ key: "FEid", data: writeFilterEffects(filterItems) });
11385
11325
  const bytes = writePsd(
11386
11326
  {
11387
- header: { psb, channels: planes.length, width, height, depth: 8, colorMode: 3 },
11327
+ header: { psb, channels: planes.length, width, height, depth, colorMode: 3 },
11388
11328
  colorModeData: new Uint8Array(0),
11389
11329
  resources,
11390
11330
  layers: records,
11391
11331
  mergedAlpha: transparent && records.length > 0,
11392
11332
  globalBlocks,
11393
- imageCompression: 1,
11394
- imageData: encodeRle(merged2, { planes: planes.length, width, height, depth: 8, psb })
11333
+ imageCompression: depth === 32 ? 0 : 1,
11334
+ imageData: depth === 32 ? merged2 : encodeRle(merged2, { planes: planes.length, width, height, depth, psb })
11395
11335
  },
11396
11336
  encodeLegacyName
11397
11337
  );
@@ -11527,6 +11467,7 @@ export {
11527
11467
  activeAdjustmentLayers,
11528
11468
  evaluateAdjustmentLayers,
11529
11469
  applyAdjustmentLayers,
11470
+ applyAdjustmentLayersFloat,
11530
11471
  adjustmentLayersKey,
11531
11472
  applyAdjustments,
11532
11473
  applyLegacyAdjustments,
@@ -11534,9 +11475,9 @@ export {
11534
11475
  applyBoxBlur,
11535
11476
  applyDepthMask,
11536
11477
  removeAlpha,
11478
+ TEXT_ALIGNS,
11537
11479
  SHAPE_OPERATIONS,
11538
11480
  LIVE_SHAPE_KINDS,
11539
- TEXT_ALIGNS,
11540
11481
  newLayerId,
11541
11482
  pixelLayers,
11542
11483
  developFilter,
@@ -11553,6 +11494,7 @@ export {
11553
11494
  depthMaskAlpha,
11554
11495
  runLayerFilters,
11555
11496
  LayerCompositor,
11497
+ compositeDeep,
11556
11498
  DEFAULT_ADJUSTMENTS_VALUES,
11557
11499
  DEFAULT_TRANSFORM_VALUES,
11558
11500
  DEFAULT_DEPTH_MASK_VALUES,
@@ -11612,18 +11554,6 @@ export {
11612
11554
  shapeFromAnnotation,
11613
11555
  annotationBlend,
11614
11556
  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
11557
  TEXT_RENDER_MARGIN,
11628
11558
  textMatrix,
11629
11559
  textOutlines,
@@ -11725,6 +11655,8 @@ export {
11725
11655
  serializePatterns,
11726
11656
  deserializePatterns,
11727
11657
  encodeSurface,
11658
+ encodeDeepSurface,
11659
+ decodeDeepSurface,
11728
11660
  serializeEffects,
11729
11661
  deserializeEffects,
11730
11662
  serializeLayer,
@@ -11764,4 +11696,4 @@ export {
11764
11696
  smartContentsFile,
11765
11697
  exportPsd
11766
11698
  };
11767
- //# sourceMappingURL=chunk-CZOXTEMN.js.map
11699
+ //# sourceMappingURL=chunk-EUVSQ25B.js.map