@pixerate/editor 0.123.0 → 0.124.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent/index.cjs +2 -2
- package/dist/agent/index.cjs.map +1 -1
- package/dist/agent/index.js +3 -3
- package/dist/animation/index.d.cts +2 -1
- package/dist/animation/index.d.ts +2 -1
- package/dist/animation-editor/index.cjs.map +1 -1
- package/dist/animation-editor/index.d.cts +11 -733
- package/dist/animation-editor/index.d.ts +11 -733
- package/dist/animation-editor/index.js.map +1 -1
- package/dist/{bezier-C-W9LFyD.d.cts → bezier-CBzKKDjl.d.cts} +2 -66
- package/dist/{bezier-DQZE5dxA.d.ts → bezier-CWv6LQal.d.ts} +2 -66
- package/dist/{brushstrokeRender-M4S65DHT.cjs → brushstrokeRender-EELTV7U4.cjs} +8 -8
- package/dist/{brushstrokeRender-M4S65DHT.cjs.map → brushstrokeRender-EELTV7U4.cjs.map} +1 -1
- package/dist/{brushstrokeRender-CDDRSV2W.js → brushstrokeRender-LRV7GXGD.js} +3 -3
- package/dist/canvas/index.cjs +6 -6
- package/dist/canvas/index.d.cts +10 -6
- package/dist/canvas/index.d.ts +10 -6
- package/dist/canvas/index.js +1 -1
- package/dist/{chunk-SMJGE7HM.cjs → chunk-4QQZV5Y5.cjs} +512 -39
- package/dist/chunk-4QQZV5Y5.cjs.map +1 -0
- package/dist/{chunk-TVXFHE4T.js → chunk-64PYNEHJ.js} +45 -12
- package/dist/chunk-64PYNEHJ.js.map +1 -0
- package/dist/{chunk-2IW3BWRT.cjs → chunk-7LQO6OHH.cjs} +2 -2
- package/dist/{chunk-2IW3BWRT.cjs.map → chunk-7LQO6OHH.cjs.map} +1 -1
- package/dist/chunk-CN4PJHUG.cjs +234 -0
- package/dist/chunk-CN4PJHUG.cjs.map +1 -0
- package/dist/chunk-FHYDQOPC.cjs +215 -0
- package/dist/chunk-FHYDQOPC.cjs.map +1 -0
- package/dist/{chunk-KMBC4HNV.js → chunk-J67OLQUQ.js} +2 -2
- package/dist/chunk-JRXJTPES.js +215 -0
- package/dist/chunk-JRXJTPES.js.map +1 -0
- package/dist/{chunk-IPFRWILU.js → chunk-ORHMVUR6.js} +488 -15
- package/dist/chunk-ORHMVUR6.js.map +1 -0
- package/dist/{chunk-6CJRDJCU.cjs → chunk-PEHYWUVV.cjs} +176 -111
- package/dist/chunk-PEHYWUVV.cjs.map +1 -0
- package/dist/chunk-QEG3GRN2.js +234 -0
- package/dist/chunk-QEG3GRN2.js.map +1 -0
- package/dist/{chunk-6ZBR4J62.js → chunk-WATAQ2Z2.js} +79 -14
- package/dist/chunk-WATAQ2Z2.js.map +1 -0
- package/dist/{chunk-RLRUAPBJ.cjs → chunk-Z6OUCS2K.cjs} +47 -14
- package/dist/chunk-Z6OUCS2K.cjs.map +1 -0
- package/dist/effects/index.cjs +605 -0
- package/dist/effects/index.cjs.map +1 -0
- package/dist/effects/index.d.cts +163 -0
- package/dist/effects/index.d.ts +163 -0
- package/dist/effects/index.js +605 -0
- package/dist/effects/index.js.map +1 -0
- package/dist/evaluate-2S3vSPLy.d.cts +55 -0
- package/dist/evaluate-CfmT6xA3.d.ts +55 -0
- package/dist/{export-DfjzHAJI.d.ts → export-BGtXgMJ3.d.ts} +536 -128
- package/dist/{export-Dv0-ZVrV.d.cts → export-BdfY_lH0.d.ts} +392 -5
- package/dist/{export-Dv0-ZVrV.d.ts → export-CbpjwxaI.d.cts} +392 -5
- package/dist/{export-lU5qSpHE.d.cts → export-WmYoWmLM.d.cts} +536 -128
- package/dist/flair-CxB3fOcU.d.ts +739 -0
- package/dist/flair-D7BxyBwL.d.cts +739 -0
- package/dist/gradient-KDfCvhuj.d.cts +66 -0
- package/dist/gradient-KDfCvhuj.d.ts +66 -0
- package/dist/helpers-777mC6dc.d.cts +253 -0
- package/dist/helpers-DX2_7L5t.d.ts +253 -0
- package/dist/image-editor/index.cjs +1296 -805
- package/dist/image-editor/index.cjs.map +1 -1
- package/dist/image-editor/index.d.cts +39 -182
- package/dist/image-editor/index.d.ts +39 -182
- package/dist/image-editor/index.js +497 -6
- package/dist/image-editor/index.js.map +1 -1
- package/dist/{opentype-p8Xxf-Wh.d.ts → opentype-14PDI5D2.d.ts} +1 -1
- package/dist/{opentype-BV7wWatY.d.cts → opentype-D80AVmMu.d.cts} +1 -1
- package/dist/paint/index.cjs +2 -2
- package/dist/paint/index.d.cts +32 -10
- package/dist/paint/index.d.ts +32 -10
- package/dist/paint/index.js +1 -1
- package/dist/paint-editor/index.cjs +10 -8
- package/dist/paint-editor/index.cjs.map +1 -1
- package/dist/paint-editor/index.d.cts +11 -5
- package/dist/paint-editor/index.d.ts +11 -5
- package/dist/paint-editor/index.js +4 -2
- package/dist/paint-editor/index.js.map +1 -1
- package/dist/parameters/index.d.cts +4 -184
- package/dist/parameters/index.d.ts +4 -184
- package/dist/{pathfinder-IxcyhO00.d.cts → pathfinder-C0UoFypx.d.cts} +1 -1
- package/dist/{pathfinder-StVChJOT.d.ts → pathfinder-DjISxkUv.d.ts} +1 -1
- package/dist/{player-DrcP2xqj.d.cts → player-CBtEoU2x.d.cts} +2 -54
- package/dist/{player-DV4Jujdq.d.ts → player-cGLrngL_.d.ts} +2 -54
- package/dist/{svg-BtND4TJu.d.cts → svg-BDrjRnL1.d.cts} +3 -2
- package/dist/{svg-BfVXG7hL.d.ts → svg-C-vZ3q50.d.ts} +3 -2
- package/dist/tools/index.cjs +2 -2
- package/dist/tools/index.cjs.map +1 -1
- package/dist/tools/index.js +3 -3
- package/dist/tools-C7JtLYzo.d.ts +126 -0
- package/dist/tools-DHKGHiSK.d.cts +126 -0
- package/dist/{types-fuXEme9j.d.ts → types-BcX7sCsn.d.ts} +2 -2
- package/dist/{types-DJF3Ghn5.d.cts → types-CznabG7m.d.cts} +2 -2
- package/dist/types-D3-J3TFf.d.ts +185 -0
- package/dist/types-DMcf_z4J.d.cts +185 -0
- package/dist/vector/index.d.cts +10 -10
- package/dist/vector/index.d.ts +10 -10
- package/dist/video-editor/index.cjs +749 -277
- package/dist/video-editor/index.cjs.map +1 -1
- package/dist/video-editor/index.d.cts +265 -138
- package/dist/video-editor/index.d.ts +265 -138
- package/dist/video-editor/index.js +490 -18
- package/dist/video-editor/index.js.map +1 -1
- package/dist/{warp-BjmAgQwq.d.cts → warp-CH9MM435.d.cts} +1 -1
- package/dist/{warp-Ca5fedzS.d.ts → warp-k_PdtXOG.d.ts} +1 -1
- package/package.json +6 -1
- package/skills/pixerate-image-editor/SKILL.md +7 -0
- package/skills/pixerate-image-editor/references/provider-effects.md +35 -0
- package/skills/pixerate-video-editor/SKILL.md +39 -1
- package/dist/chunk-6CJRDJCU.cjs.map +0 -1
- package/dist/chunk-6ZBR4J62.js.map +0 -1
- package/dist/chunk-IPFRWILU.js.map +0 -1
- package/dist/chunk-RLRUAPBJ.cjs.map +0 -1
- package/dist/chunk-SMJGE7HM.cjs.map +0 -1
- package/dist/chunk-TVXFHE4T.js.map +0 -1
- /package/dist/{brushstrokeRender-CDDRSV2W.js.map → brushstrokeRender-LRV7GXGD.js.map} +0 -0
- /package/dist/{chunk-KMBC4HNV.js.map → chunk-J67OLQUQ.js.map} +0 -0
|
@@ -51,6 +51,7 @@ import {
|
|
|
51
51
|
VIBRANCE_GREY,
|
|
52
52
|
XYZ_D50_TO_SRGB,
|
|
53
53
|
activeAdjustmentLayers,
|
|
54
|
+
activeEffectSmartFilters,
|
|
54
55
|
activeSmartFilters,
|
|
55
56
|
addLayerEffect,
|
|
56
57
|
addLayerFilter,
|
|
@@ -180,6 +181,7 @@ import {
|
|
|
180
181
|
isRenderedLayer,
|
|
181
182
|
isSelectionEmpty,
|
|
182
183
|
isSelectionMode,
|
|
184
|
+
isSmartSurfaceIncomplete,
|
|
183
185
|
isSpatialFilter,
|
|
184
186
|
isTransformAnchor,
|
|
185
187
|
isValidWarp,
|
|
@@ -197,7 +199,7 @@ import {
|
|
|
197
199
|
legacyView,
|
|
198
200
|
levelsValue,
|
|
199
201
|
linearSrgbToXy,
|
|
200
|
-
linearToSrgb,
|
|
202
|
+
linearToSrgb as linearToSrgb2,
|
|
201
203
|
liveComponent,
|
|
202
204
|
liveShapeSubpaths,
|
|
203
205
|
mapCropHandle,
|
|
@@ -360,13 +362,25 @@ import {
|
|
|
360
362
|
writePsd,
|
|
361
363
|
xyToTempTint,
|
|
362
364
|
xyToUv
|
|
363
|
-
} from "../chunk-
|
|
365
|
+
} from "../chunk-WATAQ2Z2.js";
|
|
364
366
|
import {
|
|
365
367
|
parseCssColor
|
|
366
368
|
} from "../chunk-CTTF4KYV.js";
|
|
367
369
|
import {
|
|
368
370
|
loadDocument
|
|
369
371
|
} from "../chunk-U5HZSFCS.js";
|
|
372
|
+
import {
|
|
373
|
+
createEffectToolProvider
|
|
374
|
+
} from "../chunk-JRXJTPES.js";
|
|
375
|
+
import {
|
|
376
|
+
EffectRendererPool,
|
|
377
|
+
EffectUnsupportedError,
|
|
378
|
+
EffectsSlot,
|
|
379
|
+
createEffectPixels,
|
|
380
|
+
linearToSrgb,
|
|
381
|
+
resolveEffectValues
|
|
382
|
+
} from "../chunk-QEG3GRN2.js";
|
|
383
|
+
import "../chunk-4FX5ACVG.js";
|
|
370
384
|
import {
|
|
371
385
|
createCaptureTool
|
|
372
386
|
} from "../chunk-REOJJIY3.js";
|
|
@@ -475,7 +489,7 @@ import {
|
|
|
475
489
|
pathStrokeCoverage,
|
|
476
490
|
pathStrokeDabs,
|
|
477
491
|
renderBrushstroke
|
|
478
|
-
} from "../chunk-
|
|
492
|
+
} from "../chunk-64PYNEHJ.js";
|
|
479
493
|
import {
|
|
480
494
|
BODY_SCATTER,
|
|
481
495
|
DEFAULT_FLOW,
|
|
@@ -2772,6 +2786,170 @@ function refineSelection(pixels, mask, params = {}) {
|
|
|
2772
2786
|
return createSelectionMask(mask.width, mask.height, out);
|
|
2773
2787
|
}
|
|
2774
2788
|
|
|
2789
|
+
// src/image-editor/effects.ts
|
|
2790
|
+
var IMAGE_EFFECT_PLACES = {
|
|
2791
|
+
/** A smart filter: the effect changes the pixels below it. */
|
|
2792
|
+
filter: ["filter"],
|
|
2793
|
+
/** An effect layer: drawn at the document's size. */
|
|
2794
|
+
layer: ["generator", "overlay", "title"]
|
|
2795
|
+
};
|
|
2796
|
+
function checkImageEffectPlace(d, place) {
|
|
2797
|
+
const allowed = IMAGE_EFFECT_PLACES[place];
|
|
2798
|
+
if (d.kind === "motion" || !d.uses.some((u) => allowed.includes(u))) {
|
|
2799
|
+
const instead = place === "filter" && d.uses.some((u) => IMAGE_EFFECT_PLACES.layer.includes(u)) ? "; add it as an effect layer with add_effect_layer instead" : place === "layer" && d.uses.includes("filter") ? "; apply it to a layer as a smart filter with apply_effect instead" : "";
|
|
2800
|
+
throw new EffectUnsupportedError(
|
|
2801
|
+
`"${d.id}" (${d.name}) is a ${d.uses.join(" / ")} effect, and ${place === "filter" ? "a smart filter takes filter effects" : "an effect layer takes generator, overlay or title effects"}${instead}.`,
|
|
2802
|
+
d.id
|
|
2803
|
+
);
|
|
2804
|
+
}
|
|
2805
|
+
}
|
|
2806
|
+
function over(base, top) {
|
|
2807
|
+
const out = new Uint8ClampedArray(base.length);
|
|
2808
|
+
for (let i = 0; i < out.length; i += 4) {
|
|
2809
|
+
const ta = top[i + 3] / 255;
|
|
2810
|
+
const ba = base[i + 3] / 255;
|
|
2811
|
+
const a = ta + ba * (1 - ta);
|
|
2812
|
+
out[i + 3] = Math.round(a * 255);
|
|
2813
|
+
if (a > 0) for (let c = 0; c < 3; c++) out[i + c] = (top[i + c] * ta + base[i + c] * ba * (1 - ta)) / a;
|
|
2814
|
+
}
|
|
2815
|
+
return out;
|
|
2816
|
+
}
|
|
2817
|
+
function effectPixelsToSurface(p, depth) {
|
|
2818
|
+
if (depth === 8 || !p.float) return surfaceFromPixels({ width: p.width, height: p.height, data: p.data }, 4);
|
|
2819
|
+
if (depth === 32) return surfaceFromDeepPixels({ width: p.width, height: p.height, data: p.float }, 4);
|
|
2820
|
+
const f = p.float;
|
|
2821
|
+
const d = new Uint16Array(f.length);
|
|
2822
|
+
const code = (v) => v > 0 ? v < 1 ? Math.round(v * 65535) : 65535 : 0;
|
|
2823
|
+
for (let i = 0; i < f.length; i += 4) {
|
|
2824
|
+
d[i] = code(linearToSrgb(f[i]));
|
|
2825
|
+
d[i + 1] = code(linearToSrgb(f[i + 1]));
|
|
2826
|
+
d[i + 2] = code(linearToSrgb(f[i + 2]));
|
|
2827
|
+
d[i + 3] = code(f[i + 3]);
|
|
2828
|
+
}
|
|
2829
|
+
return surfaceFromDeepPixels({ width: p.width, height: p.height, data: d }, 4);
|
|
2830
|
+
}
|
|
2831
|
+
var ImageEffectsEngine = class {
|
|
2832
|
+
slot;
|
|
2833
|
+
cache = /* @__PURE__ */ new Map();
|
|
2834
|
+
pending = /* @__PURE__ */ new Map();
|
|
2835
|
+
failures = /* @__PURE__ */ new Map();
|
|
2836
|
+
pool;
|
|
2837
|
+
descriptions = /* @__PURE__ */ new Map();
|
|
2838
|
+
listeners = /* @__PURE__ */ new Set();
|
|
2839
|
+
maxEntries;
|
|
2840
|
+
generation = 0;
|
|
2841
|
+
detach;
|
|
2842
|
+
constructor(options = {}) {
|
|
2843
|
+
this.slot = options.slot ?? new EffectsSlot();
|
|
2844
|
+
this.maxEntries = options.maxEntries ?? 24;
|
|
2845
|
+
this.pool = new EffectRendererPool({ maxRenderers: options.maxRenderers });
|
|
2846
|
+
this.detach = this.slot.subscribe(() => {
|
|
2847
|
+
this.reset();
|
|
2848
|
+
this.notify();
|
|
2849
|
+
});
|
|
2850
|
+
}
|
|
2851
|
+
get provider() {
|
|
2852
|
+
return this.slot.provider;
|
|
2853
|
+
}
|
|
2854
|
+
/** See `SmartEffectResolver.token`: bumped when the provider changes. */
|
|
2855
|
+
get token() {
|
|
2856
|
+
return this.generation;
|
|
2857
|
+
}
|
|
2858
|
+
/** True while a render is under way. */
|
|
2859
|
+
get busy() {
|
|
2860
|
+
return this.pending.size > 0;
|
|
2861
|
+
}
|
|
2862
|
+
/** See `SmartEffectResolver`. */
|
|
2863
|
+
resolve(filter, input, width, height, key) {
|
|
2864
|
+
const hit = this.cache.get(key);
|
|
2865
|
+
if (hit) {
|
|
2866
|
+
this.cache.delete(key);
|
|
2867
|
+
this.cache.set(key, hit);
|
|
2868
|
+
return { result: hit, pending: false };
|
|
2869
|
+
}
|
|
2870
|
+
if (this.pending.has(key)) return { result: null, pending: true };
|
|
2871
|
+
const provider = this.slot.provider;
|
|
2872
|
+
if (!provider || this.failures.has(key)) return { result: null, pending: false };
|
|
2873
|
+
const generation = this.generation;
|
|
2874
|
+
const source = { width, height, data: new Uint8ClampedArray(input) };
|
|
2875
|
+
const run = this.filter(provider, filter.effect, filter.values, source).then((out) => {
|
|
2876
|
+
if (generation !== this.generation) return;
|
|
2877
|
+
this.cache.set(key, out);
|
|
2878
|
+
while (this.cache.size > this.maxEntries) this.cache.delete(this.cache.keys().next().value);
|
|
2879
|
+
}).catch((error) => {
|
|
2880
|
+
if (generation === this.generation) this.failures.set(key, error instanceof Error ? error : new Error(String(error)));
|
|
2881
|
+
}).finally(() => {
|
|
2882
|
+
if (this.pending.get(key) === run) this.pending.delete(key);
|
|
2883
|
+
if (generation === this.generation) this.notify();
|
|
2884
|
+
});
|
|
2885
|
+
this.pending.set(key, run);
|
|
2886
|
+
return { result: null, pending: true };
|
|
2887
|
+
}
|
|
2888
|
+
/** A filter effect over `source`: its result, or (for an overlay) the effect drawn over it. */
|
|
2889
|
+
async filter(provider, effect, values, source) {
|
|
2890
|
+
const d = await this.describe(provider, effect);
|
|
2891
|
+
const takesSource = d.inputs.some((i) => i.name === "source");
|
|
2892
|
+
const out = await this.render(provider, effect, source.width, source.height, 8, { time: 0, values, ...takesSource ? { inputs: { source } } : {} });
|
|
2893
|
+
return takesSource ? out.data : over(source.data, out.data);
|
|
2894
|
+
}
|
|
2895
|
+
/**
|
|
2896
|
+
* Renders a generator or overlay effect at a size and depth (an effect layer's pixels). Rejects
|
|
2897
|
+
* with the provider's error, or without a provider.
|
|
2898
|
+
*/
|
|
2899
|
+
async renderLayer(effect, values, size) {
|
|
2900
|
+
const provider = this.slot.require();
|
|
2901
|
+
const depth = size.depth ?? 8;
|
|
2902
|
+
const out = await this.render(provider, effect, size.width, size.height, depth, { time: size.time ?? 0, values });
|
|
2903
|
+
return out.width === size.width && out.height === size.height ? out : createEffectPixels(size.width, size.height);
|
|
2904
|
+
}
|
|
2905
|
+
/** Why the result for `key` failed, if it did. */
|
|
2906
|
+
failure(key) {
|
|
2907
|
+
return this.failures.get(key);
|
|
2908
|
+
}
|
|
2909
|
+
/** Every failure so far. */
|
|
2910
|
+
failuresList() {
|
|
2911
|
+
return [...this.failures].map(([key, error]) => ({ key, error }));
|
|
2912
|
+
}
|
|
2913
|
+
/** Resolves when nothing is rendering. */
|
|
2914
|
+
async idle() {
|
|
2915
|
+
while (this.pending.size) await Promise.all([...this.pending.values()]);
|
|
2916
|
+
}
|
|
2917
|
+
/** The provider's description of an effect, fetched once per provider. */
|
|
2918
|
+
describe(provider, id) {
|
|
2919
|
+
let d = this.descriptions.get(id);
|
|
2920
|
+
if (!d) {
|
|
2921
|
+
d = Promise.resolve().then(() => provider.describe(id));
|
|
2922
|
+
d.catch(() => this.descriptions.delete(id));
|
|
2923
|
+
this.descriptions.set(id, d);
|
|
2924
|
+
}
|
|
2925
|
+
return d;
|
|
2926
|
+
}
|
|
2927
|
+
render(provider, id, width, height, depth, request) {
|
|
2928
|
+
return this.pool.render(provider, id, { width, height, depth }, request);
|
|
2929
|
+
}
|
|
2930
|
+
/** Forgets every result and failure and disposes the renderers. */
|
|
2931
|
+
reset() {
|
|
2932
|
+
this.generation++;
|
|
2933
|
+
this.cache.clear();
|
|
2934
|
+
this.pending.clear();
|
|
2935
|
+
this.failures.clear();
|
|
2936
|
+
this.descriptions.clear();
|
|
2937
|
+
this.pool.clear();
|
|
2938
|
+
}
|
|
2939
|
+
subscribe(listener) {
|
|
2940
|
+
this.listeners.add(listener);
|
|
2941
|
+
return () => this.listeners.delete(listener);
|
|
2942
|
+
}
|
|
2943
|
+
notify() {
|
|
2944
|
+
for (const l of [...this.listeners]) l();
|
|
2945
|
+
}
|
|
2946
|
+
destroy() {
|
|
2947
|
+
this.reset();
|
|
2948
|
+
this.detach();
|
|
2949
|
+
this.listeners.clear();
|
|
2950
|
+
}
|
|
2951
|
+
};
|
|
2952
|
+
|
|
2775
2953
|
// src/image-editor/free-transform.ts
|
|
2776
2954
|
var FREE_TRANSFORM_CONTENTS = ["auto", "layer", "selection", "selection-copy", "selection-outline"];
|
|
2777
2955
|
var fail = (message) => {
|
|
@@ -3885,7 +4063,15 @@ var ImageEditorController = class {
|
|
|
3885
4063
|
viewKey = [];
|
|
3886
4064
|
/** For `compositePixels` and mask evaluation (the renderer keeps its own for the viewport). */
|
|
3887
4065
|
compositor = new LayerCompositor();
|
|
4066
|
+
/** The effects provider slot (see `setEffectsProvider`). */
|
|
4067
|
+
effects = new EffectsSlot();
|
|
4068
|
+
/** Renders provider effects: effect smart filter results and effect layers. */
|
|
4069
|
+
effectsEngine = new ImageEffectsEngine({ slot: this.effects });
|
|
4070
|
+
effectRefresh = "none";
|
|
3888
4071
|
constructor(options = {}) {
|
|
4072
|
+
this.effects.subscribe(() => this.queueEffectRefresh("all"));
|
|
4073
|
+
this.effectsEngine.subscribe(() => this.queueEffectRefresh("incomplete"));
|
|
4074
|
+
if (options.effects) this.effects.set(options.effects);
|
|
3889
4075
|
this.maxHistoryDepth = options.maxHistoryDepth ?? 50;
|
|
3890
4076
|
if (options.textShaper !== void 0) this.textShaperValue = options.textShaper;
|
|
3891
4077
|
this.maxHistoryBytes = options.maxHistoryBytes ?? 512 * 1024 * 1024;
|
|
@@ -4019,6 +4205,206 @@ var ImageEditorController = class {
|
|
|
4019
4205
|
const currentState = { ...this.state };
|
|
4020
4206
|
this.onStateChange?.(currentState);
|
|
4021
4207
|
this.listeners.forEach((l) => l(currentState));
|
|
4208
|
+
if (this.effects.provider) this.queueEffectRefresh("incomplete");
|
|
4209
|
+
}
|
|
4210
|
+
// --- Provider effects ---
|
|
4211
|
+
queueEffectRefresh(kind) {
|
|
4212
|
+
const queued = this.effectRefresh !== "none";
|
|
4213
|
+
if (kind === "all" || this.effectRefresh === "none") this.effectRefresh = kind;
|
|
4214
|
+
if (queued) return;
|
|
4215
|
+
queueMicrotask(() => {
|
|
4216
|
+
const all = this.effectRefresh === "all";
|
|
4217
|
+
this.effectRefresh = "none";
|
|
4218
|
+
this.refreshEffectSurfaces(all);
|
|
4219
|
+
});
|
|
4220
|
+
}
|
|
4221
|
+
/**
|
|
4222
|
+
* Renders smart objects with effect filters again: every one (`all`, after the provider changed)
|
|
4223
|
+
* or those drawn while a result was rendering, once it is in. A cache refresh: no undo step.
|
|
4224
|
+
*/
|
|
4225
|
+
refreshEffectSurfaces(all) {
|
|
4226
|
+
let changed = false;
|
|
4227
|
+
const canvas = this.canvasSize;
|
|
4228
|
+
const walk = (layers) => {
|
|
4229
|
+
let out = null;
|
|
4230
|
+
layers.forEach((l, i) => {
|
|
4231
|
+
let next2 = l;
|
|
4232
|
+
if (l.type === "group") {
|
|
4233
|
+
const children = walk(l.children);
|
|
4234
|
+
if (children !== l.children) next2 = { ...l, children };
|
|
4235
|
+
} else if (l.type === "smart" && l.smartFilters?.filters.some((f) => f.kind === "effect") && (all || isSmartSurfaceIncomplete(l.surface))) {
|
|
4236
|
+
try {
|
|
4237
|
+
const r = rerender(l, canvas);
|
|
4238
|
+
if (all || !isSmartSurfaceIncomplete(r.surface)) next2 = r;
|
|
4239
|
+
} catch {
|
|
4240
|
+
}
|
|
4241
|
+
}
|
|
4242
|
+
if (next2 !== l) {
|
|
4243
|
+
out ??= [...layers];
|
|
4244
|
+
out[i] = next2;
|
|
4245
|
+
changed = true;
|
|
4246
|
+
}
|
|
4247
|
+
});
|
|
4248
|
+
return out ?? layers;
|
|
4249
|
+
};
|
|
4250
|
+
const next = walk(this.state.layers);
|
|
4251
|
+
if (!changed) return;
|
|
4252
|
+
this.state.layers = next;
|
|
4253
|
+
this.notify();
|
|
4254
|
+
}
|
|
4255
|
+
/** The registered effects provider, or `null`. */
|
|
4256
|
+
get effectsProvider() {
|
|
4257
|
+
return this.effects.provider;
|
|
4258
|
+
}
|
|
4259
|
+
/** Registers (or with `null` removes) the effects provider. Not an edit: no undo step. */
|
|
4260
|
+
setEffectsProvider(provider) {
|
|
4261
|
+
this.effects.set(provider);
|
|
4262
|
+
}
|
|
4263
|
+
/** Registers `provider` and returns a function that removes it again (if it is still the one set). */
|
|
4264
|
+
useEffects(provider) {
|
|
4265
|
+
return this.effects.use(provider);
|
|
4266
|
+
}
|
|
4267
|
+
/** The provider's description of an effect, checked for `place` (rejects without a provider or for an unknown id). */
|
|
4268
|
+
async describeEffect(effect, place) {
|
|
4269
|
+
const provider = this.effects.require();
|
|
4270
|
+
const d = await this.effectsEngine.describe(provider, effect);
|
|
4271
|
+
if (place) checkImageEffectPlace(d, place);
|
|
4272
|
+
return d;
|
|
4273
|
+
}
|
|
4274
|
+
/** Resolves when every effect render has landed and the surfaces waiting for them are drawn. */
|
|
4275
|
+
async effectsIdle() {
|
|
4276
|
+
const tick = () => new Promise((r) => queueMicrotask(r));
|
|
4277
|
+
for (let round6 = 0; round6 < 32; round6++) {
|
|
4278
|
+
await this.effectsEngine.idle();
|
|
4279
|
+
await tick();
|
|
4280
|
+
await tick();
|
|
4281
|
+
if (!this.effectsEngine.busy && this.effectRefresh === "none") return;
|
|
4282
|
+
}
|
|
4283
|
+
}
|
|
4284
|
+
/**
|
|
4285
|
+
* Applies a provider filter effect as a smart filter (at `index`, default the top), one undo
|
|
4286
|
+
* step. A pixel, shape or type layer (or a group) is first converted to a smart object in the
|
|
4287
|
+
* same step (Filter › Convert for Smart Filters), keeping its id when it is one layer. `values`
|
|
4288
|
+
* are checked against the effect's controls and stored over its defaults.
|
|
4289
|
+
*/
|
|
4290
|
+
async applyEffectFilter(layerId, effect, options = {}) {
|
|
4291
|
+
const d = await this.describeEffect(effect, "filter");
|
|
4292
|
+
const values = resolveEffectValues(d, options.values);
|
|
4293
|
+
const found = findLayer(this.state.layers, layerId);
|
|
4294
|
+
if (!found) throw new LayerOperationError(`There is no layer "${layerId}"; call list_layers for the layer ids.`);
|
|
4295
|
+
let layers = this.state.layers;
|
|
4296
|
+
let id = layerId;
|
|
4297
|
+
let converted = false;
|
|
4298
|
+
if (found.layer.type !== "smart") {
|
|
4299
|
+
if (found.layer.type === "adjustment" || found.layer.type === "annotation") throw new LayerOperationError(`Layer "${found.layer.name || layerId}" is ${found.layer.type === "adjustment" ? "an adjustment layer" : "an annotation"}, which has no pixels to filter; apply the effect to a pixel layer or smart object.`);
|
|
4300
|
+
const res2 = convertToSmartObject(layers, [layerId], this.canvasSize, { surfaceOf: (l) => this.surfaceOf(l) });
|
|
4301
|
+
layers = res2.layers;
|
|
4302
|
+
id = res2.layer.id;
|
|
4303
|
+
converted = true;
|
|
4304
|
+
}
|
|
4305
|
+
const filter = normalizeSmartFilter({ kind: "effect", effect: d.id, provider: this.effects.require().id, name: d.name, values, enabled: options.enabled !== false, blend: options.blend, opacity: options.opacity });
|
|
4306
|
+
const res = addSmartFilter(layers, id, filter, this.canvasSize, options.index);
|
|
4307
|
+
this.commitLayers(res.layers);
|
|
4308
|
+
return { layerId: id, filter: res.filter, converted };
|
|
4309
|
+
}
|
|
4310
|
+
/**
|
|
4311
|
+
* Changes an effect smart filter: `values` merged over its own (`null` resets a control to the
|
|
4312
|
+
* effect's default), `enabled`, `blend`, `opacity` or its place in the stack (`index`). Values
|
|
4313
|
+
* are checked against the provider's controls. One undo step (none with `commitToHistory`
|
|
4314
|
+
* false, during a drag).
|
|
4315
|
+
*/
|
|
4316
|
+
async updateEffectFilter(layerId, filterId, changes, commitToHistory = true) {
|
|
4317
|
+
const layer = requireSmartObject(this.state.layers, layerId);
|
|
4318
|
+
const was = layer.smartFilters?.filters.find((f) => f.id === filterId);
|
|
4319
|
+
if (!was || was.kind !== "effect") throw new LayerOperationError(`Smart object "${layer.name || layerId}" has no effect filter "${filterId}"; its filters are ${(layer.smartFilters?.filters ?? []).map((f) => `${f.id} (${f.kind === "effect" ? f.name ?? f.effect : f.kind})`).join(", ") || "none"}.`);
|
|
4320
|
+
const update = {};
|
|
4321
|
+
if (changes.values) {
|
|
4322
|
+
const d = await this.describeEffect(was.effect);
|
|
4323
|
+
const given = {};
|
|
4324
|
+
const base = { ...was.values };
|
|
4325
|
+
for (const [k, v] of Object.entries(changes.values)) {
|
|
4326
|
+
if (v !== null) given[k] = v;
|
|
4327
|
+
else if (k in d.controls.properties) base[k] = d.defaults[k];
|
|
4328
|
+
else throw new LayerOperationError(`"${k}" is not a control of "${d.id}"; its controls are ${Object.keys(d.controls.properties).join(", ")}.`);
|
|
4329
|
+
}
|
|
4330
|
+
update.values = { ...base, ...resolveEffectValues({ ...d, defaults: base }, given) };
|
|
4331
|
+
}
|
|
4332
|
+
for (const k of ["enabled", "blend", "opacity"]) if (changes[k] !== void 0) update[k] = changes[k];
|
|
4333
|
+
let res = updateSmartFilter(this.state.layers, layerId, filterId, update, this.canvasSize);
|
|
4334
|
+
if (changes.index !== void 0) res = { ...res, layers: moveSmartFilter(res.layers, layerId, filterId, changes.index, this.canvasSize).layers };
|
|
4335
|
+
this.commitLayers(res.layers, void 0, commitToHistory);
|
|
4336
|
+
return requireSmartObject(this.state.layers, layerId).smartFilters.filters.find((f) => f.id === filterId);
|
|
4337
|
+
}
|
|
4338
|
+
/**
|
|
4339
|
+
* Adds an effect layer: a pixel layer drawn by a provider generator, overlay or title effect at
|
|
4340
|
+
* the document's size and bit depth (at `time` ms, default 0), placed like `addPixelLayer`. One
|
|
4341
|
+
* undo step. Masks, blend and opacity apply as to any layer. Returns its id.
|
|
4342
|
+
*/
|
|
4343
|
+
async addEffectLayer(effect, options = {}) {
|
|
4344
|
+
const d = await this.describeEffect(effect, "layer");
|
|
4345
|
+
const values = resolveEffectValues(d, options.values);
|
|
4346
|
+
const { width, height } = this.naturalSize;
|
|
4347
|
+
const pixels = await this.effectsEngine.renderLayer(d.id, values, { width, height, depth: this.bitDepth, time: options.time });
|
|
4348
|
+
const blend = parseBlend(options.blend);
|
|
4349
|
+
if (options.opacity !== void 0 && !(options.opacity >= 0 && options.opacity <= 1)) throw new LayerOperationError("opacity must be from 0 to 1.");
|
|
4350
|
+
const ids = new Set(flattenLayers(this.state.layers).map((l) => l.id));
|
|
4351
|
+
const layer = {
|
|
4352
|
+
type: "pixel",
|
|
4353
|
+
id: options.id && !ids.has(options.id) ? options.id : newLayerId(),
|
|
4354
|
+
name: options.name?.trim() || d.name,
|
|
4355
|
+
visible: true,
|
|
4356
|
+
opacity: options.opacity ?? 1,
|
|
4357
|
+
blend: blend ?? "normal",
|
|
4358
|
+
surface: effectPixelsToSurface(pixels, this.bitDepth),
|
|
4359
|
+
offset: { x: 0, y: 0 },
|
|
4360
|
+
generator: { effect: d.id, provider: this.effects.require().id, name: d.name, values, ...options.time ? { time: options.time } : {} }
|
|
4361
|
+
};
|
|
4362
|
+
const next = placeLayer(this.state.layers, layer, this.newLayerPlacement(options));
|
|
4363
|
+
this.commitLayers(next, () => {
|
|
4364
|
+
this.state.activeLayerId = layer.id;
|
|
4365
|
+
this.state.activeTarget = "pixels";
|
|
4366
|
+
});
|
|
4367
|
+
return layer.id;
|
|
4368
|
+
}
|
|
4369
|
+
/**
|
|
4370
|
+
* Draws an effect layer again with new `values` (merged over its own; `null` resets a control)
|
|
4371
|
+
* or `time`, at the document's size and depth, replacing its pixels (painting on it is lost).
|
|
4372
|
+
* One undo step (none with `commitToHistory` false). Returns its effect settings.
|
|
4373
|
+
*/
|
|
4374
|
+
async updateEffectLayer(layerId, changes, commitToHistory = true) {
|
|
4375
|
+
const found = findLayer(this.state.layers, layerId);
|
|
4376
|
+
const layer = found?.layer;
|
|
4377
|
+
if (!layer || layer.type !== "pixel" || !layer.generator) throw new LayerOperationError(`"${layerId}" is not an effect layer; add one with add_effect_layer.`);
|
|
4378
|
+
requireUnlocked(layer, "pixels", "draw its effect again");
|
|
4379
|
+
const g = layer.generator;
|
|
4380
|
+
const d = await this.describeEffect(g.effect);
|
|
4381
|
+
const base = { ...g.values };
|
|
4382
|
+
const given = {};
|
|
4383
|
+
for (const [k, v] of Object.entries(changes.values ?? {})) {
|
|
4384
|
+
if (v !== null) given[k] = v;
|
|
4385
|
+
else if (k in d.controls.properties) base[k] = d.defaults[k];
|
|
4386
|
+
else throw new LayerOperationError(`"${k}" is not a control of "${d.id}"; its controls are ${Object.keys(d.controls.properties).join(", ")}.`);
|
|
4387
|
+
}
|
|
4388
|
+
const values = { ...base, ...resolveEffectValues({ ...d, defaults: base }, given) };
|
|
4389
|
+
const time = changes.time ?? g.time ?? 0;
|
|
4390
|
+
const { width, height } = this.naturalSize;
|
|
4391
|
+
const pixels = await this.effectsEngine.renderLayer(d.id, values, { width, height, depth: this.bitDepth, time });
|
|
4392
|
+
const generator = { ...g, values, provider: this.effects.require().id, ...time ? { time } : {} };
|
|
4393
|
+
if (!time) delete generator.time;
|
|
4394
|
+
const next = mapLayer(this.state.layers, layerId, (l) => ({ ...l, surface: effectPixelsToSurface(pixels, this.bitDepth), offset: { x: 0, y: 0 }, generator }));
|
|
4395
|
+
this.commitLayers(next, void 0, commitToHistory);
|
|
4396
|
+
return generator;
|
|
4397
|
+
}
|
|
4398
|
+
/** Turns an effect layer into a plain pixel layer keeping its pixels (one undo step). */
|
|
4399
|
+
rasterizeEffectLayer(layerId) {
|
|
4400
|
+
const found = findLayer(this.state.layers, layerId);
|
|
4401
|
+
if (!found || found.layer.type !== "pixel" || !found.layer.generator) throw new LayerOperationError(`"${layerId}" is not an effect layer.`);
|
|
4402
|
+
this.commitLayers(
|
|
4403
|
+
mapLayer(this.state.layers, layerId, (l) => {
|
|
4404
|
+
const { generator: _g, ...rest } = l;
|
|
4405
|
+
return rest;
|
|
4406
|
+
})
|
|
4407
|
+
);
|
|
4022
4408
|
}
|
|
4023
4409
|
displayFor = null;
|
|
4024
4410
|
/** Keeps the renderer's display transform in step with the document profile, mode and Proof Setup. */
|
|
@@ -4918,7 +5304,7 @@ var ImageEditorController = class {
|
|
|
4918
5304
|
}
|
|
4919
5305
|
// --- Smart objects ---
|
|
4920
5306
|
get canvasSize() {
|
|
4921
|
-
return this.naturalSize;
|
|
5307
|
+
return { ...this.naturalSize, effects: this.effectsEngine };
|
|
4922
5308
|
}
|
|
4923
5309
|
/**
|
|
4924
5310
|
* Layer › Smart Objects › Convert to Smart Object (one undo step): sibling layers (default the
|
|
@@ -13440,7 +13826,7 @@ function smartFilterRows(layer) {
|
|
|
13440
13826
|
filter: f,
|
|
13441
13827
|
index,
|
|
13442
13828
|
drawn: f.kind !== "psd",
|
|
13443
|
-
label: f.kind === "psd" ? f.name.replace(/&/g, "").replace(/\.\.\.$/, "") : f.kind === "blur" ? `Blur (${f.radius} px)` : "Develop"
|
|
13829
|
+
label: f.kind === "psd" ? f.name.replace(/&/g, "").replace(/\.\.\.$/, "") : f.kind === "effect" ? f.name ?? f.effect : f.kind === "blur" ? `Blur (${f.radius} px)` : "Develop"
|
|
13444
13830
|
}));
|
|
13445
13831
|
return rows.reverse();
|
|
13446
13832
|
}
|
|
@@ -14295,6 +14681,103 @@ var FreeTransformTool = class {
|
|
|
14295
14681
|
return false;
|
|
14296
14682
|
}
|
|
14297
14683
|
};
|
|
14684
|
+
|
|
14685
|
+
// src/image-editor/provider-effect-tools.ts
|
|
14686
|
+
function imageLayerAppliedEffects(layer) {
|
|
14687
|
+
const out = [];
|
|
14688
|
+
const ref = (r) => ({ effect: r.effect, ...r.name ? { name: r.name } : {}, ...r.provider ? { provider: r.provider } : {} });
|
|
14689
|
+
if (layer.type === "pixel" && layer.generator) out.push({ id: "generator", ...ref(layer.generator), role: "effect layer", enabled: true, values: layer.generator.values, ...layer.generator.time ? { time: layer.generator.time } : {} });
|
|
14690
|
+
if (layer.type === "smart")
|
|
14691
|
+
(layer.smartFilters?.filters ?? []).forEach((f, index) => {
|
|
14692
|
+
if (f.kind === "effect") out.push({ id: f.id, ...ref(f), role: "smart filter", enabled: f.enabled && layer.smartFilters.enabled, opacity: f.opacity, blend: f.blend, values: f.values, index });
|
|
14693
|
+
});
|
|
14694
|
+
return out;
|
|
14695
|
+
}
|
|
14696
|
+
function createImageEffectsToolProvider(controller, options = {}) {
|
|
14697
|
+
const readOnlyReason = () => {
|
|
14698
|
+
const ro = typeof options.readOnly === "function" ? options.readOnly() : options.readOnly;
|
|
14699
|
+
return ro ? typeof ro === "string" ? ro : "The image is read-only." : null;
|
|
14700
|
+
};
|
|
14701
|
+
const layerOf = (id) => {
|
|
14702
|
+
const found = findLayer(controller.getState().layers, id);
|
|
14703
|
+
if (!found) {
|
|
14704
|
+
const ids = flattenLayers(controller.getState().layers).map((l) => `"${l.id}"`);
|
|
14705
|
+
throw new Error(`There is no layer "${id}"; the layers are ${ids.join(", ") || "none"} (list_layers lists them).`);
|
|
14706
|
+
}
|
|
14707
|
+
return found.layer;
|
|
14708
|
+
};
|
|
14709
|
+
const result = (target, instance, extra = {}) => {
|
|
14710
|
+
const effects = imageLayerAppliedEffects(layerOf(target));
|
|
14711
|
+
return { target, effect: effects.find((e) => e.id === instance) ?? effects[effects.length - 1], effects, ...extra };
|
|
14712
|
+
};
|
|
14713
|
+
const plainValues = (v) => v;
|
|
14714
|
+
return createEffectToolProvider({
|
|
14715
|
+
id: options.id ?? "image-effects",
|
|
14716
|
+
namespace: options.namespace,
|
|
14717
|
+
target: { noun: "layer", id: "A layer id from list_layers." },
|
|
14718
|
+
applyUses: ["filter"],
|
|
14719
|
+
applyDetails: "The effect becomes a smart filter: it runs on the layer's pixels after the smart filters below it, with its own blend and opacity, under the smart filter mask, and can be changed or removed later. A pixel, shape or type layer (or a group) is converted to a smart object first, in the same undo step (one layer keeps its id; the result says converted). Generators and overlays go on their own layer through add_effect_layer.",
|
|
14720
|
+
provider: () => controller.effectsProvider,
|
|
14721
|
+
readOnlyReason,
|
|
14722
|
+
list: (target) => {
|
|
14723
|
+
const layers = target ? [layerOf(target)] : flattenLayers(controller.getState().layers);
|
|
14724
|
+
return layers.map((l) => ({ target: l.id, ...l.name ? { name: l.name } : {}, effects: imageLayerAppliedEffects(l) })).filter((t) => target || t.effects.length);
|
|
14725
|
+
},
|
|
14726
|
+
apply: async (target, effect, args) => {
|
|
14727
|
+
const r = await controller.applyEffectFilter(target, effect, { values: plainValues(args.values), index: args.index, enabled: args.enabled, opacity: args.opacity });
|
|
14728
|
+
return result(r.layerId, r.filter.id, { converted: r.converted });
|
|
14729
|
+
},
|
|
14730
|
+
update: async (target, instance, changes) => {
|
|
14731
|
+
const layer = layerOf(target);
|
|
14732
|
+
if (instance === "generator") {
|
|
14733
|
+
const extra = ["enabled", "opacity", "index"].filter((k) => changes[k] !== void 0);
|
|
14734
|
+
if (extra.length) throw new Error(`An effect layer's own effect only takes values; change the layer's ${extra.join(", ")} with update_layer.`);
|
|
14735
|
+
if (layer.type !== "pixel" || !layer.generator) throw new Error(`"${target}" is not an effect layer.`);
|
|
14736
|
+
await controller.updateEffectLayer(target, { values: changes.values });
|
|
14737
|
+
return result(target, "generator");
|
|
14738
|
+
}
|
|
14739
|
+
await controller.updateEffectFilter(target, instance, { values: changes.values, enabled: changes.enabled, opacity: changes.opacity, index: changes.index });
|
|
14740
|
+
return result(target, instance);
|
|
14741
|
+
},
|
|
14742
|
+
remove: async (target, instance) => {
|
|
14743
|
+
const layer = layerOf(target);
|
|
14744
|
+
const was = imageLayerAppliedEffects(layer).find((e) => e.id === instance);
|
|
14745
|
+
if (!was) throw new Error(`Layer "${layer.name || target}" has no provider effect "${instance}"; its effects are ${imageLayerAppliedEffects(layer).map((e) => `"${e.id}"`).join(", ") || "none"} (list_applied_effects).`);
|
|
14746
|
+
if (instance === "generator") controller.rasterizeEffectLayer(target);
|
|
14747
|
+
else controller.removeSmartFilter(target, instance);
|
|
14748
|
+
return { target, effect: was, effects: imageLayerAppliedEffects(layerOf(target)) };
|
|
14749
|
+
},
|
|
14750
|
+
subscribe: (notify) => controller.subscribe(() => notify()),
|
|
14751
|
+
extraTools: (ctx) => [
|
|
14752
|
+
{
|
|
14753
|
+
name: "add_effect_layer",
|
|
14754
|
+
title: "Add an effect layer",
|
|
14755
|
+
description: `Adds a layer drawn by a provider generator, overlay or title effect (search_effects with use generator, overlay or title) at the document's size and bit depth, above the active layer unless placed. Masks, blend mode, opacity and layer styles apply as to any layer; transparent effects show the layers beneath. update_effect with effect "generator" draws it again with new values; remove_effect "generator" keeps its pixels as a plain layer. One undo step. Returns the new layer id and its effect.`,
|
|
14756
|
+
inputSchema: {
|
|
14757
|
+
type: "object",
|
|
14758
|
+
properties: {
|
|
14759
|
+
effect: ctx.effectIdSchema(["generator", "overlay", "title"]),
|
|
14760
|
+
values: ctx.valuesSchema("Control values over the effect's defaults"),
|
|
14761
|
+
time: { type: "number", minimum: 0, description: "Which moment of an animated effect to draw, in ms (default 0)." },
|
|
14762
|
+
name: { type: "string", minLength: 1, description: "The layer name (default: the effect's name)." },
|
|
14763
|
+
aboveId: { type: "string", minLength: 1, description: "Put it directly above this layer (default: above the active layer, else on top)." },
|
|
14764
|
+
belowId: { type: "string", minLength: 1, description: "Put it directly below this layer." },
|
|
14765
|
+
opacity: { type: "number", minimum: 0, maximum: 1, description: "Layer opacity 0\u20131 (default 1)." },
|
|
14766
|
+
blend: { type: "string", enum: BLEND_MODES.map((m) => m.id).filter((b) => b !== "pigment"), description: "Layer blend mode (default normal); screen or add for light effects, multiply for textures." }
|
|
14767
|
+
},
|
|
14768
|
+
required: ["effect"],
|
|
14769
|
+
additionalProperties: false
|
|
14770
|
+
},
|
|
14771
|
+
annotations: { title: "Add an effect layer", ...ctx.annotations.write },
|
|
14772
|
+
handler: async (args) => {
|
|
14773
|
+
ctx.requireProvider();
|
|
14774
|
+
const id = await controller.addEffectLayer(args.effect, { values: plainValues(args.values), time: args.time, name: args.name, aboveId: args.aboveId, belowId: args.belowId, opacity: args.opacity, blend: args.blend });
|
|
14775
|
+
return { layerId: id, effects: imageLayerAppliedEffects(layerOf(id)) };
|
|
14776
|
+
}
|
|
14777
|
+
}
|
|
14778
|
+
]
|
|
14779
|
+
});
|
|
14780
|
+
}
|
|
14298
14781
|
export {
|
|
14299
14782
|
ADJUSTMENT_KEYS,
|
|
14300
14783
|
ADJUSTMENT_KINDS,
|
|
@@ -14372,12 +14855,14 @@ export {
|
|
|
14372
14855
|
IMAGE_CROP_PRESETS,
|
|
14373
14856
|
IMAGE_EDITOR_SCHEMA_VERSION,
|
|
14374
14857
|
IMAGE_EDITOR_STATE_VERSION,
|
|
14858
|
+
IMAGE_EFFECT_PLACES,
|
|
14375
14859
|
IMAGE_FILTER_PRESETS,
|
|
14376
14860
|
INTENTS,
|
|
14377
14861
|
INTENT_OPTIONS,
|
|
14378
14862
|
INTERPOLATIONS,
|
|
14379
14863
|
ImageEditorController,
|
|
14380
14864
|
ImageEditorRenderer,
|
|
14865
|
+
ImageEffectsEngine,
|
|
14381
14866
|
LATEST_PROCESS_VERSION,
|
|
14382
14867
|
LAYERED_SCHEMA_VERSION,
|
|
14383
14868
|
LAYER_EFFECT_KINDS,
|
|
@@ -14522,6 +15007,7 @@ export {
|
|
|
14522
15007
|
XYZ_D50_TO_SRGB,
|
|
14523
15008
|
ZlibError,
|
|
14524
15009
|
activeAdjustmentLayers,
|
|
15010
|
+
activeEffectSmartFilters,
|
|
14525
15011
|
activeSmartFilters,
|
|
14526
15012
|
addLayerEffect,
|
|
14527
15013
|
addLayerFilter,
|
|
@@ -14599,6 +15085,7 @@ export {
|
|
|
14599
15085
|
canvasToImagePoint,
|
|
14600
15086
|
caretAt,
|
|
14601
15087
|
changedTiles,
|
|
15088
|
+
checkImageEffectPlace,
|
|
14602
15089
|
clampControlValue,
|
|
14603
15090
|
clampCropToImage,
|
|
14604
15091
|
cleanMixer,
|
|
@@ -14638,6 +15125,7 @@ export {
|
|
|
14638
15125
|
createImageEditTools,
|
|
14639
15126
|
createImageEditorToolProvider,
|
|
14640
15127
|
createImageEffectTools,
|
|
15128
|
+
createImageEffectsToolProvider,
|
|
14641
15129
|
createImageLayerTools,
|
|
14642
15130
|
createImagePaintTools,
|
|
14643
15131
|
createImagePsdTools,
|
|
@@ -14716,6 +15204,7 @@ export {
|
|
|
14716
15204
|
edgeWidth,
|
|
14717
15205
|
effectColorHex,
|
|
14718
15206
|
effectControlChange,
|
|
15207
|
+
effectPixelsToSurface,
|
|
14719
15208
|
effectReach,
|
|
14720
15209
|
effectiveProof,
|
|
14721
15210
|
effectsFingerprint,
|
|
@@ -14797,6 +15286,7 @@ export {
|
|
|
14797
15286
|
identityTransform,
|
|
14798
15287
|
identityWarpMesh,
|
|
14799
15288
|
imageEditorStateMigrations,
|
|
15289
|
+
imageLayerAppliedEffects,
|
|
14800
15290
|
imageToCanvasPoint,
|
|
14801
15291
|
importPsd,
|
|
14802
15292
|
inflate,
|
|
@@ -14831,6 +15321,7 @@ export {
|
|
|
14831
15321
|
isSelectionEmpty,
|
|
14832
15322
|
isSelectionMode,
|
|
14833
15323
|
isSeparableBlendMode,
|
|
15324
|
+
isSmartSurfaceIncomplete,
|
|
14834
15325
|
isSpatialFilter,
|
|
14835
15326
|
isSrgb,
|
|
14836
15327
|
isTransformAnchor,
|
|
@@ -14866,7 +15357,7 @@ export {
|
|
|
14866
15357
|
lerpPigmentInto,
|
|
14867
15358
|
levelsValue,
|
|
14868
15359
|
linearSrgbToXy,
|
|
14869
|
-
linearToSrgb,
|
|
15360
|
+
linearToSrgb2 as linearToSrgb,
|
|
14870
15361
|
linearToSrgb8,
|
|
14871
15362
|
liveComponent,
|
|
14872
15363
|
liveShapeForDrag,
|