@pixerate/editor 0.188.0 → 0.190.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-IGMNJM2H.js → chunk-7ZWLDVFH.js} +979 -753
- package/dist/{chunk-JYV4R62M.cjs → chunk-T4U4O6DS.cjs} +1013 -787
- package/dist/image-editor/controller.d.cts +68 -1
- package/dist/image-editor/controller.d.ts +68 -1
- package/dist/image-editor/free-transform.d.cts +3 -6
- package/dist/image-editor/free-transform.d.ts +3 -6
- package/dist/image-editor/index.cjs +1867 -1413
- package/dist/image-editor/index.d.cts +1 -0
- package/dist/image-editor/index.d.ts +1 -0
- package/dist/image-editor/index.js +869 -415
- package/dist/image-editor/layer-tools.d.cts +1 -1
- package/dist/image-editor/layer-tools.d.ts +1 -1
- package/dist/image-editor/layers/compositor.d.cts +3 -0
- package/dist/image-editor/layers/compositor.d.ts +3 -0
- package/dist/image-editor/layers/model.d.cts +23 -0
- package/dist/image-editor/layers/model.d.ts +23 -0
- package/dist/image-editor/layers/paint-ui.d.cts +2 -1
- package/dist/image-editor/layers/paint-ui.d.ts +2 -1
- package/dist/image-editor/layers/panel.d.cts +14 -3
- package/dist/image-editor/layers/panel.d.ts +14 -3
- package/dist/image-editor/layers/serialize.d.cts +11 -0
- package/dist/image-editor/layers/serialize.d.ts +11 -0
- package/dist/image-editor/layers/shape.d.cts +5 -0
- package/dist/image-editor/layers/shape.d.ts +5 -0
- package/dist/image-editor/layers/vector-mask.d.cts +51 -0
- package/dist/image-editor/layers/vector-mask.d.ts +51 -0
- package/dist/image-editor/psd/import.d.cts +0 -7
- package/dist/image-editor/psd/import.d.ts +0 -7
- package/dist/image-editor/renderer.d.cts +6 -0
- package/dist/image-editor/renderer.d.ts +6 -0
- package/dist/image-editor/selection/gesture.d.cts +10 -0
- package/dist/image-editor/selection/gesture.d.ts +10 -0
- package/dist/image-editor/selection/layer-mask.d.cts +6 -0
- package/dist/image-editor/selection/layer-mask.d.ts +6 -0
- package/dist/image-editor/types.d.cts +8 -0
- package/dist/image-editor/types.d.ts +8 -0
- package/dist/paint-editor/index.cjs +6 -6
- package/dist/paint-editor/index.js +1 -1
- package/package.json +1 -1
- package/skills/pixerate-image-editor/SKILL.md +7 -0
- package/skills/pixerate-image-selection-masking/SKILL.md +10 -3
|
@@ -6,7 +6,7 @@ import type { CropBox } from './types.cjs';
|
|
|
6
6
|
export declare function maskSummary(mask: RasterMask | undefined): Record<string, unknown> | null;
|
|
7
7
|
/**
|
|
8
8
|
* A plain description of a layer (and its children) for agents: ids, types, names, document
|
|
9
|
-
* bounds, visibility, opacity, fill, blend, clipping, locks, mask and effects summaries and
|
|
9
|
+
* bounds, visibility, opacity, fill, blend, clipping, locks, mask, vector mask and effects summaries and
|
|
10
10
|
* whether it is active. `boundsOf` gives a pixel layer's document bounds.
|
|
11
11
|
*/
|
|
12
12
|
export declare function describeLayer(layer: ImageLayer, activeId: string | null, boundsOf: (layer: ImageLayer) => CropBox | null): Record<string, unknown>;
|
|
@@ -6,7 +6,7 @@ import type { CropBox } from './types.js';
|
|
|
6
6
|
export declare function maskSummary(mask: RasterMask | undefined): Record<string, unknown> | null;
|
|
7
7
|
/**
|
|
8
8
|
* A plain description of a layer (and its children) for agents: ids, types, names, document
|
|
9
|
-
* bounds, visibility, opacity, fill, blend, clipping, locks, mask and effects summaries and
|
|
9
|
+
* bounds, visibility, opacity, fill, blend, clipping, locks, mask, vector mask and effects summaries and
|
|
10
10
|
* whether it is active. `boundsOf` gives a pixel layer's document bounds.
|
|
11
11
|
*/
|
|
12
12
|
export declare function describeLayer(layer: ImageLayer, activeId: string | null, boundsOf: (layer: ImageLayer) => CropBox | null): Record<string, unknown>;
|
|
@@ -42,6 +42,9 @@ export declare function runLayerFiltersFloat(data: Float32Array, width: number,
|
|
|
42
42
|
/** The per-tile compositor for image editor layer stacks (see the raster module for the caches). */
|
|
43
43
|
export declare class LayerCompositor extends RasterCompositor<ImageLayer, CompositorSources> {
|
|
44
44
|
constructor(options?: CompositorOptions);
|
|
45
|
+
composite(layers: readonly ImageLayer[], rect: RasterRect, sources: CompositorSources, options?: CompositeCallOptions): Uint8ClampedArray;
|
|
46
|
+
compositeTiles(layers: readonly ImageLayer[], rect: RasterRect, sources: CompositorSources, onTile: (tx: number, ty: number, data: Uint8ClampedArray, changed: boolean) => void, options?: CompositeCallOptions): void;
|
|
47
|
+
tile(layers: readonly ImageLayer[], tx: number, ty: number, sources: CompositorSources): Uint8ClampedArray;
|
|
45
48
|
}
|
|
46
49
|
/**
|
|
47
50
|
* The composite of an image editor stack at 16 or 32 bits (see `raster/deep-compositor`): float
|
|
@@ -42,6 +42,9 @@ export declare function runLayerFiltersFloat(data: Float32Array, width: number,
|
|
|
42
42
|
/** The per-tile compositor for image editor layer stacks (see the raster module for the caches). */
|
|
43
43
|
export declare class LayerCompositor extends RasterCompositor<ImageLayer, CompositorSources> {
|
|
44
44
|
constructor(options?: CompositorOptions);
|
|
45
|
+
composite(layers: readonly ImageLayer[], rect: RasterRect, sources: CompositorSources, options?: CompositeCallOptions): Uint8ClampedArray;
|
|
46
|
+
compositeTiles(layers: readonly ImageLayer[], rect: RasterRect, sources: CompositorSources, onTile: (tx: number, ty: number, data: Uint8ClampedArray, changed: boolean) => void, options?: CompositeCallOptions): void;
|
|
47
|
+
tile(layers: readonly ImageLayer[], tx: number, ty: number, sources: CompositorSources): Uint8ClampedArray;
|
|
45
48
|
}
|
|
46
49
|
/**
|
|
47
50
|
* The composite of an image editor stack at 16 or 32 bits (see `raster/deep-compositor`): float
|
|
@@ -28,6 +28,29 @@ export type { LayerLocks };
|
|
|
28
28
|
export type RasterMask = BaseRasterMask<DepthMaskOptions>;
|
|
29
29
|
export interface LayerBase extends RasterLayerBase {
|
|
30
30
|
mask?: RasterMask;
|
|
31
|
+
/** A vector mask (Photoshop's): a path that reveals the layer, on top of `mask`. Not on shape layers. */
|
|
32
|
+
vectorMask?: VectorMask;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* A vector mask: shape components in document pixels (the same paths shape layers use) that
|
|
36
|
+
* reveal the layer inside them (outside with `inverted`). It stays sharp at any size; the
|
|
37
|
+
* compositor multiplies it with the layer's raster mask. No components hides everything
|
|
38
|
+
* (reveals everything when inverted).
|
|
39
|
+
*/
|
|
40
|
+
export interface VectorMask {
|
|
41
|
+
components: ShapeComponent[];
|
|
42
|
+
/** How overlapping subpaths fill (default nonzero). */
|
|
43
|
+
fillRule?: ShapeFillRule;
|
|
44
|
+
/** Reveal outside the path instead (default false). */
|
|
45
|
+
inverted?: boolean;
|
|
46
|
+
/** Disabled masks are kept but ignored (default true). */
|
|
47
|
+
enabled?: boolean;
|
|
48
|
+
/** `false`: the path stays put when the layer moves or transforms (default true). */
|
|
49
|
+
linked?: boolean;
|
|
50
|
+
/** 0..1 (default 1): at 0.5 the hidden area still shows half. */
|
|
51
|
+
density?: number;
|
|
52
|
+
/** Gaussian feather σ in px (default 0). */
|
|
53
|
+
feather?: number;
|
|
31
54
|
}
|
|
32
55
|
/** The base sliders of the old document-level adjustments, as a filter on one layer. */
|
|
33
56
|
export interface DevelopSettings {
|
|
@@ -28,6 +28,29 @@ export type { LayerLocks };
|
|
|
28
28
|
export type RasterMask = BaseRasterMask<DepthMaskOptions>;
|
|
29
29
|
export interface LayerBase extends RasterLayerBase {
|
|
30
30
|
mask?: RasterMask;
|
|
31
|
+
/** A vector mask (Photoshop's): a path that reveals the layer, on top of `mask`. Not on shape layers. */
|
|
32
|
+
vectorMask?: VectorMask;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* A vector mask: shape components in document pixels (the same paths shape layers use) that
|
|
36
|
+
* reveal the layer inside them (outside with `inverted`). It stays sharp at any size; the
|
|
37
|
+
* compositor multiplies it with the layer's raster mask. No components hides everything
|
|
38
|
+
* (reveals everything when inverted).
|
|
39
|
+
*/
|
|
40
|
+
export interface VectorMask {
|
|
41
|
+
components: ShapeComponent[];
|
|
42
|
+
/** How overlapping subpaths fill (default nonzero). */
|
|
43
|
+
fillRule?: ShapeFillRule;
|
|
44
|
+
/** Reveal outside the path instead (default false). */
|
|
45
|
+
inverted?: boolean;
|
|
46
|
+
/** Disabled masks are kept but ignored (default true). */
|
|
47
|
+
enabled?: boolean;
|
|
48
|
+
/** `false`: the path stays put when the layer moves or transforms (default true). */
|
|
49
|
+
linked?: boolean;
|
|
50
|
+
/** 0..1 (default 1): at 0.5 the hidden area still shows half. */
|
|
51
|
+
density?: number;
|
|
52
|
+
/** Gaussian feather σ in px (default 0). */
|
|
53
|
+
feather?: number;
|
|
31
54
|
}
|
|
32
55
|
/** The base sliders of the old document-level adjustments, as a filter on one layer. */
|
|
33
56
|
export interface DevelopSettings {
|
|
@@ -140,7 +140,8 @@ export interface ShortcutEvent {
|
|
|
140
140
|
* Applies a paint shortcut. Returns true when it was one (the caller then prevents the default).
|
|
141
141
|
* B / Shift+B (Mixer Brush) / E / V choose the tool; [ and ] change the size, with Shift the hardness by 25 %; 1..9 set the
|
|
142
142
|
* opacity to 10..90 % and 0 to 100 %; D resets the colours to black and white; X swaps them; Q
|
|
143
|
-
* toggles Quick Mask mode (painting then edits the selection)
|
|
143
|
+
* toggles Quick Mask mode (painting then edits the selection); the backslash key shows the active
|
|
144
|
+
* layer's mask as a red overlay.
|
|
144
145
|
*/
|
|
145
146
|
export declare function handlePaintShortcut(controller: ImageEditorController, e: ShortcutEvent): boolean;
|
|
146
147
|
/** One pointer sample in document pixels. */
|
|
@@ -140,7 +140,8 @@ export interface ShortcutEvent {
|
|
|
140
140
|
* Applies a paint shortcut. Returns true when it was one (the caller then prevents the default).
|
|
141
141
|
* B / Shift+B (Mixer Brush) / E / V choose the tool; [ and ] change the size, with Shift the hardness by 25 %; 1..9 set the
|
|
142
142
|
* opacity to 10..90 % and 0 to 100 %; D resets the colours to black and white; X swaps them; Q
|
|
143
|
-
* toggles Quick Mask mode (painting then edits the selection)
|
|
143
|
+
* toggles Quick Mask mode (painting then edits the selection); the backslash key shows the active
|
|
144
|
+
* layer's mask as a red overlay.
|
|
144
145
|
*/
|
|
145
146
|
export declare function handlePaintShortcut(controller: ImageEditorController, e: ShortcutEvent): boolean;
|
|
146
147
|
/** One pointer sample in document pixels. */
|
|
@@ -8,8 +8,9 @@ import { type ImageLayer, type SmartFilter } from './model.cjs';
|
|
|
8
8
|
import type { LayerPlacement } from './ops.cjs';
|
|
9
9
|
/**
|
|
10
10
|
* A click on a layer's mask thumbnail, as in Photoshop: Ctrl/⌘-click loads the mask as the
|
|
11
|
-
* selection (with Shift adding, Alt subtracting, both intersecting),
|
|
12
|
-
*
|
|
11
|
+
* selection (with Shift adding, Alt subtracting, both intersecting), Alt-click shows the mask
|
|
12
|
+
* alone in grey (Alt+Shift-click as a red overlay; again to go back to the image), Shift-click
|
|
13
|
+
* turns the mask on or off, and a plain click makes the mask the paint target.
|
|
13
14
|
*/
|
|
14
15
|
export declare function maskThumbnailClick(controller: ImageEditorController, layer: ImageLayer, e: {
|
|
15
16
|
ctrlKey?: boolean;
|
|
@@ -17,6 +18,16 @@ export declare function maskThumbnailClick(controller: ImageEditorController, la
|
|
|
17
18
|
shiftKey?: boolean;
|
|
18
19
|
altKey?: boolean;
|
|
19
20
|
}): void;
|
|
21
|
+
/**
|
|
22
|
+
* A click on a layer's vector mask thumbnail: Ctrl/⌘-click loads the path as the selection (Shift
|
|
23
|
+
* adds, Alt subtracts, both intersect) and Shift-click turns the vector mask on or off.
|
|
24
|
+
*/
|
|
25
|
+
export declare function vectorMaskThumbnailClick(controller: ImageEditorController, layer: ImageLayer, e: {
|
|
26
|
+
ctrlKey?: boolean;
|
|
27
|
+
metaKey?: boolean;
|
|
28
|
+
shiftKey?: boolean;
|
|
29
|
+
altKey?: boolean;
|
|
30
|
+
}): void;
|
|
20
31
|
/**
|
|
21
32
|
* A click on a layer's pixel thumbnail: Ctrl/⌘-click loads the layer's transparency as the
|
|
22
33
|
* selection (Shift adds, Alt subtracts, both intersect) and returns true; other clicks are left
|
|
@@ -56,7 +67,7 @@ export type DropZone = 'above' | 'below' | 'inside';
|
|
|
56
67
|
export declare function dropZone(fraction: number, isGroup: boolean): DropZone;
|
|
57
68
|
/** The placement for `move_layer` when `dragId` is dropped on row `targetId` in `zone`, or `null` for a no-op. */
|
|
58
69
|
export declare function dropPlacement(layers: readonly ImageLayer[], dragId: string, targetId: string, zone: DropZone): LayerPlacement | null;
|
|
59
|
-
export type LayerMenuAction = 'new-layer' | 'new-group' | 'duplicate' | 'delete' | 'group-selected' | 'ungroup' | 'merge-down' | 'merge-visible' | 'flatten' | 'via-copy' | 'via-cut' | 'add-mask' | 'add-mask-selection' | 'add-mask-hide-selection' | 'add-mask-transparency' | 'select-transparency' | 'apply-mask' | 'delete-mask' | 'toggle-mask' | 'toggle-mask-link' | 'toggle-clip' | 'rasterize' | 'convert-smart' | 'edit-contents' | 'smart-via-copy' | 'add-filter-mask';
|
|
70
|
+
export type LayerMenuAction = 'new-layer' | 'new-group' | 'duplicate' | 'delete' | 'group-selected' | 'ungroup' | 'merge-down' | 'merge-visible' | 'flatten' | 'via-copy' | 'via-cut' | 'add-mask' | 'add-vector-mask' | 'add-vector-mask-hide' | 'delete-vector-mask' | 'toggle-vector-mask' | 'rasterize-vector-mask' | 'add-mask-selection' | 'add-mask-hide-selection' | 'add-mask-transparency' | 'select-transparency' | 'apply-mask' | 'delete-mask' | 'toggle-mask' | 'toggle-mask-link' | 'toggle-clip' | 'rasterize' | 'convert-smart' | 'edit-contents' | 'smart-via-copy' | 'add-filter-mask';
|
|
60
71
|
export interface LayerMenuItem {
|
|
61
72
|
action: LayerMenuAction;
|
|
62
73
|
label: string;
|
|
@@ -8,8 +8,9 @@ import { type ImageLayer, type SmartFilter } from './model.js';
|
|
|
8
8
|
import type { LayerPlacement } from './ops.js';
|
|
9
9
|
/**
|
|
10
10
|
* A click on a layer's mask thumbnail, as in Photoshop: Ctrl/⌘-click loads the mask as the
|
|
11
|
-
* selection (with Shift adding, Alt subtracting, both intersecting),
|
|
12
|
-
*
|
|
11
|
+
* selection (with Shift adding, Alt subtracting, both intersecting), Alt-click shows the mask
|
|
12
|
+
* alone in grey (Alt+Shift-click as a red overlay; again to go back to the image), Shift-click
|
|
13
|
+
* turns the mask on or off, and a plain click makes the mask the paint target.
|
|
13
14
|
*/
|
|
14
15
|
export declare function maskThumbnailClick(controller: ImageEditorController, layer: ImageLayer, e: {
|
|
15
16
|
ctrlKey?: boolean;
|
|
@@ -17,6 +18,16 @@ export declare function maskThumbnailClick(controller: ImageEditorController, la
|
|
|
17
18
|
shiftKey?: boolean;
|
|
18
19
|
altKey?: boolean;
|
|
19
20
|
}): void;
|
|
21
|
+
/**
|
|
22
|
+
* A click on a layer's vector mask thumbnail: Ctrl/⌘-click loads the path as the selection (Shift
|
|
23
|
+
* adds, Alt subtracts, both intersect) and Shift-click turns the vector mask on or off.
|
|
24
|
+
*/
|
|
25
|
+
export declare function vectorMaskThumbnailClick(controller: ImageEditorController, layer: ImageLayer, e: {
|
|
26
|
+
ctrlKey?: boolean;
|
|
27
|
+
metaKey?: boolean;
|
|
28
|
+
shiftKey?: boolean;
|
|
29
|
+
altKey?: boolean;
|
|
30
|
+
}): void;
|
|
20
31
|
/**
|
|
21
32
|
* A click on a layer's pixel thumbnail: Ctrl/⌘-click loads the layer's transparency as the
|
|
22
33
|
* selection (Shift adds, Alt subtracts, both intersect) and returns true; other clicks are left
|
|
@@ -56,7 +67,7 @@ export type DropZone = 'above' | 'below' | 'inside';
|
|
|
56
67
|
export declare function dropZone(fraction: number, isGroup: boolean): DropZone;
|
|
57
68
|
/** The placement for `move_layer` when `dragId` is dropped on row `targetId` in `zone`, or `null` for a no-op. */
|
|
58
69
|
export declare function dropPlacement(layers: readonly ImageLayer[], dragId: string, targetId: string, zone: DropZone): LayerPlacement | null;
|
|
59
|
-
export type LayerMenuAction = 'new-layer' | 'new-group' | 'duplicate' | 'delete' | 'group-selected' | 'ungroup' | 'merge-down' | 'merge-visible' | 'flatten' | 'via-copy' | 'via-cut' | 'add-mask' | 'add-mask-selection' | 'add-mask-hide-selection' | 'add-mask-transparency' | 'select-transparency' | 'apply-mask' | 'delete-mask' | 'toggle-mask' | 'toggle-mask-link' | 'toggle-clip' | 'rasterize' | 'convert-smart' | 'edit-contents' | 'smart-via-copy' | 'add-filter-mask';
|
|
70
|
+
export type LayerMenuAction = 'new-layer' | 'new-group' | 'duplicate' | 'delete' | 'group-selected' | 'ungroup' | 'merge-down' | 'merge-visible' | 'flatten' | 'via-copy' | 'via-cut' | 'add-mask' | 'add-vector-mask' | 'add-vector-mask-hide' | 'delete-vector-mask' | 'toggle-vector-mask' | 'rasterize-vector-mask' | 'add-mask-selection' | 'add-mask-hide-selection' | 'add-mask-transparency' | 'select-transparency' | 'apply-mask' | 'delete-mask' | 'toggle-mask' | 'toggle-mask-link' | 'toggle-clip' | 'rasterize' | 'convert-smart' | 'edit-contents' | 'smart-via-copy' | 'add-filter-mask';
|
|
60
71
|
export interface LayerMenuItem {
|
|
61
72
|
action: LayerMenuAction;
|
|
62
73
|
label: string;
|
|
@@ -40,9 +40,20 @@ interface SerializedLayerBase {
|
|
|
40
40
|
blend: string;
|
|
41
41
|
clipped?: boolean;
|
|
42
42
|
mask?: SerializedRasterMask;
|
|
43
|
+
vectorMask?: SerializedVectorMask;
|
|
43
44
|
locks?: LayerLocks;
|
|
44
45
|
effects?: SerializedLayerEffects;
|
|
45
46
|
}
|
|
47
|
+
/** A stored vector mask: its components as JSON (document pixels) and its properties. */
|
|
48
|
+
export interface SerializedVectorMask {
|
|
49
|
+
components: unknown[];
|
|
50
|
+
fillRule?: 'evenodd';
|
|
51
|
+
inverted?: true;
|
|
52
|
+
enabled?: false;
|
|
53
|
+
linked?: false;
|
|
54
|
+
density?: number;
|
|
55
|
+
feather?: number;
|
|
56
|
+
}
|
|
46
57
|
/** A layer's effects: the effect list as JSON plus the PSD block they came from (base64). */
|
|
47
58
|
export interface SerializedLayerEffects {
|
|
48
59
|
enabled: boolean;
|
|
@@ -40,9 +40,20 @@ interface SerializedLayerBase {
|
|
|
40
40
|
blend: string;
|
|
41
41
|
clipped?: boolean;
|
|
42
42
|
mask?: SerializedRasterMask;
|
|
43
|
+
vectorMask?: SerializedVectorMask;
|
|
43
44
|
locks?: LayerLocks;
|
|
44
45
|
effects?: SerializedLayerEffects;
|
|
45
46
|
}
|
|
47
|
+
/** A stored vector mask: its components as JSON (document pixels) and its properties. */
|
|
48
|
+
export interface SerializedVectorMask {
|
|
49
|
+
components: unknown[];
|
|
50
|
+
fillRule?: 'evenodd';
|
|
51
|
+
inverted?: true;
|
|
52
|
+
enabled?: false;
|
|
53
|
+
linked?: false;
|
|
54
|
+
density?: number;
|
|
55
|
+
feather?: number;
|
|
56
|
+
}
|
|
46
57
|
/** A layer's effects: the effect list as JSON plus the PSD block they came from (base64). */
|
|
47
58
|
export interface SerializedLayerEffects {
|
|
48
59
|
enabled: boolean;
|
|
@@ -50,6 +50,11 @@ export declare function shapeGeometryBounds(layer: Pick<ShapeLayer, 'components'
|
|
|
50
50
|
width: number;
|
|
51
51
|
height: number;
|
|
52
52
|
} | null;
|
|
53
|
+
/**
|
|
54
|
+
* Coverage (0..1) of `components` over `rect`, filled with `rule` and combined by their ops;
|
|
55
|
+
* `inverted` covers the outside instead. Used for vector masks.
|
|
56
|
+
*/
|
|
57
|
+
export declare function componentsCoverage(components: readonly ShapeComponent[], rect: CropBox, rule?: ShapeFillRule, inverted?: boolean): Float32Array;
|
|
53
58
|
/** Where a shape renders: the canvas grown by the margin. */
|
|
54
59
|
export declare function shapeRenderClip(env: Pick<ShapeEnv, 'width' | 'height'>): CropBox;
|
|
55
60
|
/**
|
|
@@ -50,6 +50,11 @@ export declare function shapeGeometryBounds(layer: Pick<ShapeLayer, 'components'
|
|
|
50
50
|
width: number;
|
|
51
51
|
height: number;
|
|
52
52
|
} | null;
|
|
53
|
+
/**
|
|
54
|
+
* Coverage (0..1) of `components` over `rect`, filled with `rule` and combined by their ops;
|
|
55
|
+
* `inverted` covers the outside instead. Used for vector masks.
|
|
56
|
+
*/
|
|
57
|
+
export declare function componentsCoverage(components: readonly ShapeComponent[], rect: CropBox, rule?: ShapeFillRule, inverted?: boolean): Float32Array;
|
|
53
58
|
/** Where a shape renders: the canvas grown by the margin. */
|
|
54
59
|
export declare function shapeRenderClip(env: Pick<ShapeEnv, 'width' | 'height'>): CropBox;
|
|
55
60
|
/**
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vector masks: a path on a layer that reveals it (Photoshop's Layer › Vector Mask). The paths are
|
|
3
|
+
* shape components in document pixels; the compositor sees them through `resolveVectorMasks`, which
|
|
4
|
+
* gives each layer with a vector mask a raster mask that is its raster mask times the path's
|
|
5
|
+
* coverage, so the tile engine and its caches need nothing new.
|
|
6
|
+
*/
|
|
7
|
+
import type { CropBox } from '../types.cjs';
|
|
8
|
+
import type { AffineMatrix } from '../../geom/types.cjs';
|
|
9
|
+
import type { ImageLayer, RasterMask, VectorMask } from './model.cjs';
|
|
10
|
+
/** Whether a vector mask takes part in compositing. */
|
|
11
|
+
export declare function isActiveVectorMask(vm: VectorMask | undefined): vm is VectorMask;
|
|
12
|
+
/**
|
|
13
|
+
* The vector mask's coverage (0..1) over the `width × height` canvas, with its feather and
|
|
14
|
+
* density applied.
|
|
15
|
+
*/
|
|
16
|
+
export declare function vectorMaskCoverage(vm: VectorMask, width: number, height: number): Float32Array;
|
|
17
|
+
/**
|
|
18
|
+
* The raster mask a layer composites with: its raster mask times its vector mask (layer space,
|
|
19
|
+
* feather and density baked in), or the raster mask alone when there is no active vector mask.
|
|
20
|
+
* A depth (parametric) mask cannot be combined, so it wins.
|
|
21
|
+
*/
|
|
22
|
+
export declare function effectiveLayerMask(layer: ImageLayer, width: number, height: number): RasterMask | undefined;
|
|
23
|
+
/**
|
|
24
|
+
* The stack as the compositor should see it: each layer with an active vector mask replaced by a
|
|
25
|
+
* copy whose `mask` is `effectiveLayerMask` (cached per layer object and canvas size, so the
|
|
26
|
+
* engine's tile caches keep working). Returns `layers` itself when there are none.
|
|
27
|
+
*/
|
|
28
|
+
export declare function resolveVectorMasks(layers: readonly ImageLayer[], width: number, height: number): readonly ImageLayer[];
|
|
29
|
+
/** A vector mask moved by (dx, dy) document pixels. */
|
|
30
|
+
export declare function offsetVectorMask(vm: VectorMask, dx: number, dy: number): VectorMask;
|
|
31
|
+
/** A vector mask with its paths mapped by `f` (document space); `affine` keeps live shapes live. */
|
|
32
|
+
export declare function transformVectorMask(vm: VectorMask, f: (p: {
|
|
33
|
+
x: number;
|
|
34
|
+
y: number;
|
|
35
|
+
}) => {
|
|
36
|
+
x: number;
|
|
37
|
+
y: number;
|
|
38
|
+
}, affine?: AffineMatrix): VectorMask;
|
|
39
|
+
/** A linked vector mask moved with its layer by (dx, dy); unlinked ones stay. */
|
|
40
|
+
export declare function followLayerMove<T extends ImageLayer>(layer: T, dx: number, dy: number): T;
|
|
41
|
+
/** Bounds of a vector mask's paths (document pixels), or `null` when it has none. */
|
|
42
|
+
export declare function vectorMaskBounds(vm: VectorMask): CropBox | null;
|
|
43
|
+
/**
|
|
44
|
+
* A vector mask's thumbnail over the `width × height` canvas, at most `maxSide` px: grey RGBA,
|
|
45
|
+
* white where the path reveals (cached per mask object).
|
|
46
|
+
*/
|
|
47
|
+
export declare function vectorMaskThumbnail(vm: VectorMask, width: number, height: number, maxSide?: number): {
|
|
48
|
+
width: number;
|
|
49
|
+
height: number;
|
|
50
|
+
data: Uint8ClampedArray;
|
|
51
|
+
};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vector masks: a path on a layer that reveals it (Photoshop's Layer › Vector Mask). The paths are
|
|
3
|
+
* shape components in document pixels; the compositor sees them through `resolveVectorMasks`, which
|
|
4
|
+
* gives each layer with a vector mask a raster mask that is its raster mask times the path's
|
|
5
|
+
* coverage, so the tile engine and its caches need nothing new.
|
|
6
|
+
*/
|
|
7
|
+
import type { CropBox } from '../types.js';
|
|
8
|
+
import type { AffineMatrix } from '../../geom/types.js';
|
|
9
|
+
import type { ImageLayer, RasterMask, VectorMask } from './model.js';
|
|
10
|
+
/** Whether a vector mask takes part in compositing. */
|
|
11
|
+
export declare function isActiveVectorMask(vm: VectorMask | undefined): vm is VectorMask;
|
|
12
|
+
/**
|
|
13
|
+
* The vector mask's coverage (0..1) over the `width × height` canvas, with its feather and
|
|
14
|
+
* density applied.
|
|
15
|
+
*/
|
|
16
|
+
export declare function vectorMaskCoverage(vm: VectorMask, width: number, height: number): Float32Array;
|
|
17
|
+
/**
|
|
18
|
+
* The raster mask a layer composites with: its raster mask times its vector mask (layer space,
|
|
19
|
+
* feather and density baked in), or the raster mask alone when there is no active vector mask.
|
|
20
|
+
* A depth (parametric) mask cannot be combined, so it wins.
|
|
21
|
+
*/
|
|
22
|
+
export declare function effectiveLayerMask(layer: ImageLayer, width: number, height: number): RasterMask | undefined;
|
|
23
|
+
/**
|
|
24
|
+
* The stack as the compositor should see it: each layer with an active vector mask replaced by a
|
|
25
|
+
* copy whose `mask` is `effectiveLayerMask` (cached per layer object and canvas size, so the
|
|
26
|
+
* engine's tile caches keep working). Returns `layers` itself when there are none.
|
|
27
|
+
*/
|
|
28
|
+
export declare function resolveVectorMasks(layers: readonly ImageLayer[], width: number, height: number): readonly ImageLayer[];
|
|
29
|
+
/** A vector mask moved by (dx, dy) document pixels. */
|
|
30
|
+
export declare function offsetVectorMask(vm: VectorMask, dx: number, dy: number): VectorMask;
|
|
31
|
+
/** A vector mask with its paths mapped by `f` (document space); `affine` keeps live shapes live. */
|
|
32
|
+
export declare function transformVectorMask(vm: VectorMask, f: (p: {
|
|
33
|
+
x: number;
|
|
34
|
+
y: number;
|
|
35
|
+
}) => {
|
|
36
|
+
x: number;
|
|
37
|
+
y: number;
|
|
38
|
+
}, affine?: AffineMatrix): VectorMask;
|
|
39
|
+
/** A linked vector mask moved with its layer by (dx, dy); unlinked ones stay. */
|
|
40
|
+
export declare function followLayerMove<T extends ImageLayer>(layer: T, dx: number, dy: number): T;
|
|
41
|
+
/** Bounds of a vector mask's paths (document pixels), or `null` when it has none. */
|
|
42
|
+
export declare function vectorMaskBounds(vm: VectorMask): CropBox | null;
|
|
43
|
+
/**
|
|
44
|
+
* A vector mask's thumbnail over the `width × height` canvas, at most `maxSide` px: grey RGBA,
|
|
45
|
+
* white where the path reveals (cached per mask object).
|
|
46
|
+
*/
|
|
47
|
+
export declare function vectorMaskThumbnail(vm: VectorMask, width: number, height: number, maxSide?: number): {
|
|
48
|
+
width: number;
|
|
49
|
+
height: number;
|
|
50
|
+
data: Uint8ClampedArray;
|
|
51
|
+
};
|
|
@@ -1,10 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* PSD / PSB → our layer tree. Everything the model holds maps directly (smart objects with their
|
|
3
|
-
* embedded contents, placement, warp, smart filters and filter mask; shape layers with their
|
|
4
|
-
* paths, fill, stroke and live shapes; type layers with their text, styles and Photoshop's pixels
|
|
5
|
-
* until edited); everything else comes in as close as it can (fill layers as their stored pixels)
|
|
6
|
-
* with a warning naming the layers.
|
|
7
|
-
*/
|
|
8
1
|
import { type PsdAlphaChannel } from './channels.cjs';
|
|
9
2
|
import type { ImageLayer, LayerBlendMode } from '../layers/model.cjs';
|
|
10
3
|
import { type PsdFile } from './file.cjs';
|
|
@@ -1,10 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* PSD / PSB → our layer tree. Everything the model holds maps directly (smart objects with their
|
|
3
|
-
* embedded contents, placement, warp, smart filters and filter mask; shape layers with their
|
|
4
|
-
* paths, fill, stroke and live shapes; type layers with their text, styles and Photoshop's pixels
|
|
5
|
-
* until edited); everything else comes in as close as it can (fill layers as their stored pixels)
|
|
6
|
-
* with a warning naming the layers.
|
|
7
|
-
*/
|
|
8
1
|
import { type PsdAlphaChannel } from './channels.js';
|
|
9
2
|
import type { ImageLayer, LayerBlendMode } from '../layers/model.js';
|
|
10
3
|
import { type PsdFile } from './file.js';
|
|
@@ -178,6 +178,12 @@ export declare class ImageEditorRenderer {
|
|
|
178
178
|
/** An empty selection of the image's size (Quick Mask mode with nothing selected). */
|
|
179
179
|
private emptyMask;
|
|
180
180
|
private overlayCache;
|
|
181
|
+
private maskViewCache;
|
|
182
|
+
private grayCache;
|
|
183
|
+
/** A layer's mask as canvas-sized coverage for its mask view, kept while the mask is unchanged. */
|
|
184
|
+
private maskViewSelection;
|
|
185
|
+
/** A mask alone in grey (white = revealed), opaque, drawn in natural image space. */
|
|
186
|
+
private drawMaskGray;
|
|
181
187
|
/** A channel's tint (colour, opacity, masked or selected area), drawn in natural image space. */
|
|
182
188
|
private drawMaskOverlay;
|
|
183
189
|
/** Rubylith over the unselected area, drawn in natural image space. */
|
|
@@ -178,6 +178,12 @@ export declare class ImageEditorRenderer {
|
|
|
178
178
|
/** An empty selection of the image's size (Quick Mask mode with nothing selected). */
|
|
179
179
|
private emptyMask;
|
|
180
180
|
private overlayCache;
|
|
181
|
+
private maskViewCache;
|
|
182
|
+
private grayCache;
|
|
183
|
+
/** A layer's mask as canvas-sized coverage for its mask view, kept while the mask is unchanged. */
|
|
184
|
+
private maskViewSelection;
|
|
185
|
+
/** A mask alone in grey (white = revealed), opaque, drawn in natural image space. */
|
|
186
|
+
private drawMaskGray;
|
|
181
187
|
/** A channel's tint (colour, opacity, masked or selected area), drawn in natural image space. */
|
|
182
188
|
private drawMaskOverlay;
|
|
183
189
|
/** Rubylith over the unselected area, drawn in natural image space. */
|
|
@@ -76,6 +76,16 @@ export declare function handleSelectionShortcut(controller: ImageEditorControlle
|
|
|
76
76
|
shiftKey?: boolean;
|
|
77
77
|
altKey?: boolean;
|
|
78
78
|
}, onError?: (message: string) => void): boolean;
|
|
79
|
+
/**
|
|
80
|
+
* The backslash key (no modifiers) shows or hides the active layer's mask as a red overlay; it
|
|
81
|
+
* does nothing when the layer has no painted mask. Returns true when the key was used.
|
|
82
|
+
*/
|
|
83
|
+
export declare function handleMaskViewKey(controller: ImageEditorController, e: {
|
|
84
|
+
key: string;
|
|
85
|
+
ctrlKey?: boolean;
|
|
86
|
+
metaKey?: boolean;
|
|
87
|
+
altKey?: boolean;
|
|
88
|
+
}): boolean;
|
|
79
89
|
/** Q (no modifiers) toggles Quick Mask mode. Returns true when the key was used. */
|
|
80
90
|
export declare function handleQuickMaskKey(controller: ImageEditorController, e: {
|
|
81
91
|
key: string;
|
|
@@ -76,6 +76,16 @@ export declare function handleSelectionShortcut(controller: ImageEditorControlle
|
|
|
76
76
|
shiftKey?: boolean;
|
|
77
77
|
altKey?: boolean;
|
|
78
78
|
}, onError?: (message: string) => void): boolean;
|
|
79
|
+
/**
|
|
80
|
+
* The backslash key (no modifiers) shows or hides the active layer's mask as a red overlay; it
|
|
81
|
+
* does nothing when the layer has no painted mask. Returns true when the key was used.
|
|
82
|
+
*/
|
|
83
|
+
export declare function handleMaskViewKey(controller: ImageEditorController, e: {
|
|
84
|
+
key: string;
|
|
85
|
+
ctrlKey?: boolean;
|
|
86
|
+
metaKey?: boolean;
|
|
87
|
+
altKey?: boolean;
|
|
88
|
+
}): boolean;
|
|
79
89
|
/** Q (no modifiers) toggles Quick Mask mode. Returns true when the key was used. */
|
|
80
90
|
export declare function handleQuickMaskKey(controller: ImageEditorController, e: {
|
|
81
91
|
key: string;
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import type { AdjustmentLayer, AdjustmentLayerMask } from '../types.cjs';
|
|
2
2
|
import { type ImageProjection } from '../geometry.cjs';
|
|
3
3
|
import { type SelectionMask } from './mask.cjs';
|
|
4
|
+
import type { ImageLayer } from '../layers/model.cjs';
|
|
5
|
+
/**
|
|
6
|
+
* A layer's painted mask over the `width × height` canvas as coverage (white = revealed), its
|
|
7
|
+
* pixels before density and feather; `null` without one (a depth mask is computed, not painted).
|
|
8
|
+
*/
|
|
9
|
+
export declare function layerMaskSelection(layer: ImageLayer, width: number, height: number): SelectionMask | null;
|
|
4
10
|
/** Properties of a layer mask that leave its pixels intact (Photoshop's Properties › Masks). */
|
|
5
11
|
export interface LayerMaskProps {
|
|
6
12
|
/** 0..1 (default 1): at 0.5 the masked-out areas still get half of the adjustment. */
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import type { AdjustmentLayer, AdjustmentLayerMask } from '../types.js';
|
|
2
2
|
import { type ImageProjection } from '../geometry.js';
|
|
3
3
|
import { type SelectionMask } from './mask.js';
|
|
4
|
+
import type { ImageLayer } from '../layers/model.js';
|
|
5
|
+
/**
|
|
6
|
+
* A layer's painted mask over the `width × height` canvas as coverage (white = revealed), its
|
|
7
|
+
* pixels before density and feather; `null` without one (a depth mask is computed, not painted).
|
|
8
|
+
*/
|
|
9
|
+
export declare function layerMaskSelection(layer: ImageLayer, width: number, height: number): SelectionMask | null;
|
|
4
10
|
/** Properties of a layer mask that leave its pixels intact (Photoshop's Properties › Masks). */
|
|
5
11
|
export interface LayerMaskProps {
|
|
6
12
|
/** 0..1 (default 1): at 0.5 the masked-out areas still get half of the adjustment. */
|
|
@@ -314,6 +314,14 @@ export interface ImageEditorState {
|
|
|
314
314
|
quickMask?: boolean;
|
|
315
315
|
/** How the canvas shows the selection (view state; `quickMask` mirrors `'quickMask'`). */
|
|
316
316
|
selectionDisplay?: 'ants' | 'quickMask' | 'none';
|
|
317
|
+
/**
|
|
318
|
+
* A layer mask shown on the canvas (view state, not saved): `gray` shows the mask alone in
|
|
319
|
+
* grey (Alt-click its thumbnail), `overlay` tints what it hides in red over the image (the \ key).
|
|
320
|
+
*/
|
|
321
|
+
maskView?: {
|
|
322
|
+
layerId: string;
|
|
323
|
+
mode: 'gray' | 'overlay';
|
|
324
|
+
} | null;
|
|
317
325
|
/**
|
|
318
326
|
* Quick Mask mode: painting and fills without a layer edit the selection itself (white
|
|
319
327
|
* selects, black deselects), shown as a tint. View state; the edits are undo steps.
|
|
@@ -314,6 +314,14 @@ export interface ImageEditorState {
|
|
|
314
314
|
quickMask?: boolean;
|
|
315
315
|
/** How the canvas shows the selection (view state; `quickMask` mirrors `'quickMask'`). */
|
|
316
316
|
selectionDisplay?: 'ants' | 'quickMask' | 'none';
|
|
317
|
+
/**
|
|
318
|
+
* A layer mask shown on the canvas (view state, not saved): `gray` shows the mask alone in
|
|
319
|
+
* grey (Alt-click its thumbnail), `overlay` tints what it hides in red over the image (the \ key).
|
|
320
|
+
*/
|
|
321
|
+
maskView?: {
|
|
322
|
+
layerId: string;
|
|
323
|
+
mode: 'gray' | 'overlay';
|
|
324
|
+
} | null;
|
|
317
325
|
/**
|
|
318
326
|
* Quick Mask mode: painting and fills without a layer edit the selection itself (white
|
|
319
327
|
* selects, black deselects), shown as a tint. View state; the edits are undo steps.
|
|
@@ -7,7 +7,7 @@ var _chunkZ64NRDEHcjs = require('../chunk-Z64NRDEH.cjs');
|
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
|
|
10
|
-
var
|
|
10
|
+
var _chunkT4U4O6DScjs = require('../chunk-T4U4O6DS.cjs');
|
|
11
11
|
require('../chunk-A2IS7EHE.cjs');
|
|
12
12
|
|
|
13
13
|
|
|
@@ -1653,11 +1653,11 @@ function header(state, options) {
|
|
|
1653
1653
|
return out;
|
|
1654
1654
|
}
|
|
1655
1655
|
function serializePaintDocument(state, options = {}) {
|
|
1656
|
-
const { layers, assets } =
|
|
1656
|
+
const { layers, assets } = _chunkT4U4O6DScjs.serializeLayers.call(void 0, state.layers);
|
|
1657
1657
|
return { ...header(state, options), layers, assets };
|
|
1658
1658
|
}
|
|
1659
1659
|
async function serializePaintDocumentExternal(state, store, options = {}) {
|
|
1660
|
-
const { layers, assets } = await
|
|
1660
|
+
const { layers, assets } = await _chunkT4U4O6DScjs.serializeLayersExternal.call(void 0, state.layers, store);
|
|
1661
1661
|
return { ...header(state, options), layers, assets };
|
|
1662
1662
|
}
|
|
1663
1663
|
function paintLayersOnly(layers, problems) {
|
|
@@ -1694,7 +1694,7 @@ function deserializePaintDocument(raw) {
|
|
|
1694
1694
|
const canvas = normalizeCanvas({ width: r.width, height: r.height, dpi: _nullishCoalesce(r.dpi, () => ( void 0)) });
|
|
1695
1695
|
const paper = _chunkYQ5C5BVKcjs.normalizePaper.call(void 0, _nullishCoalesce(r.paper, () => ( {})));
|
|
1696
1696
|
const assets = r.assets && typeof r.assets === "object" ? r.assets : {};
|
|
1697
|
-
const layers = paintLayersOnly(
|
|
1697
|
+
const layers = paintLayersOnly(_chunkT4U4O6DScjs.deserializeLayers.call(void 0, r.layers, { assets, problems }), problems);
|
|
1698
1698
|
const wanted = typeof r.activeLayerId === "string" ? r.activeLayerId : null;
|
|
1699
1699
|
const activeLayerId = wanted && _chunkHGTDMKNEcjs.findLayer.call(void 0, layers, wanted) ? wanted : _nullishCoalesce(_optionalChain([_chunkHGTDMKNEcjs.flattenLayers.call(void 0, layers), 'access', _70 => _70.filter, 'call', _71 => _71((l) => l.type === "pixel"), 'access', _72 => _72.pop, 'call', _73 => _73(), 'optionalAccess', _74 => _74.id]), () => ( null));
|
|
1700
1700
|
const wetEvents = Array.isArray(r.wetEvents) ? r.wetEvents.filter((e) => e && typeof e === "object" && Number.isInteger(e.clock) && typeof e.kind === "string") : [];
|
|
@@ -1710,7 +1710,7 @@ async function deserializePaintDocumentAsync(raw, store) {
|
|
|
1710
1710
|
if (!raw || typeof raw !== "object") throw new Error("Not a paint document: expected a JSON object.");
|
|
1711
1711
|
const r = raw;
|
|
1712
1712
|
const problems = [];
|
|
1713
|
-
const assets = await
|
|
1713
|
+
const assets = await _chunkT4U4O6DScjs.resolveExternalAssets.call(void 0, _nullishCoalesce(r.assets, () => ( {})), store, problems);
|
|
1714
1714
|
const loaded = deserializePaintDocument({ ...r, assets });
|
|
1715
1715
|
return { ...loaded, problems: [...problems, ...loaded.problems] };
|
|
1716
1716
|
}
|
|
@@ -5409,7 +5409,7 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
|
|
|
5409
5409
|
return next.type === "group" ? { ...next, children: toStandard(next.children) } : next;
|
|
5410
5410
|
});
|
|
5411
5411
|
const layers = toStandard(dried);
|
|
5412
|
-
const result =
|
|
5412
|
+
const result = _chunkT4U4O6DScjs.exportPsd.call(void 0, { width, height, layers: [paperLayer, ...layers], merged, resolution: dpi });
|
|
5413
5413
|
for (const [mode, names] of changed) {
|
|
5414
5414
|
const label = _nullishCoalesce(_optionalChain([_chunkCWM3CUUXcjs.BLEND_MODES, 'access', _271 => _271.find, 'call', _272 => _272((m) => m.id === mode), 'optionalAccess', _273 => _273.label]), () => ( mode));
|
|
5415
5415
|
const std = _nullishCoalesce(_optionalChain([_chunkCWM3CUUXcjs.BLEND_MODES, 'access', _274 => _274.find, 'call', _275 => _275((m) => m.id === _chunkCWM3CUUXcjs.standardBlendMode.call(void 0, mode)), 'optionalAccess', _276 => _276.label]), () => ( _chunkCWM3CUUXcjs.standardBlendMode.call(void 0, mode)));
|
package/package.json
CHANGED
|
@@ -297,6 +297,7 @@ in the source frame at the document's bit depth, colour mode and profile. Read
|
|
|
297
297
|
| `add_layer_mask` | Mask any layer `from` `reveal-all`, `hide-all`, `selection`, `hide-selection` (its inverse) or `transparency` (the layer's own alpha), with optional `density` / `feather`. Replaces an existing mask. Returns the mask summary. |
|
|
298
298
|
| `set_layer_mask_properties` | Change any layer mask's `density`, `feather`, `enabled` or `linked` (false: the mask stays put when the layer moves or transforms) without touching its pixels. |
|
|
299
299
|
| `apply_layer_mask` | Bake a pixel layer's mask into its alpha and remove it. Destructive. |
|
|
300
|
+
| `set_mask_view` | Show a layer's mask to check it (`view` `gray` alone, `overlay` red tint over what it hides, `off`; `layerId`, default active). View state only; look with `capture_view` `includeOverlays: true`, then `off`. Returns `{view, layerId}`. |
|
|
300
301
|
| `remove_layer_mask` | Delete a mask without applying it; disable it instead to keep it. |
|
|
301
302
|
| `layer_via_copy` | Copy the selected pixels of a pixel layer (default the active one) to a new layer above it; `cut: true` removes them from the source. Needs a selection. Returns the new layer. |
|
|
302
303
|
| `rasterize_layer` | Turn a shape layer into a pixel layer showing the same pixels (same id, mask, effects, opacity, blend; the paths are gone), an annotation layer into pixels (browser only), a smart object into a pixel layer (as `rasterize_smart_object`), or bake a pixel layer's develop / blur filters into its pixels. Do it before painting over a shape or annotation, or when the user wants the filters fixed. Destructive. |
|
|
@@ -312,6 +313,12 @@ in the source frame at the document's bit depth, colour mode and profile. Read
|
|
|
312
313
|
| `add_shape_component` | Add a live shape or path to a shape layer with `op` (`combine`, `subtract`, `intersect`, `exclude`), on top unless `index`. Use it for cut-outs, rings, badges. Returns the shape. |
|
|
313
314
|
| `remove_shape_component` | Delete one component (not the last: delete the layer instead). Returns the shape. |
|
|
314
315
|
| `merge_shape_components` | Merge Shape Components: the combined area becomes one plain component (live shapes become paths); the look does not change. Returns the shape. |
|
|
316
|
+
| `get_vector_mask` | Read-only. A layer's vector mask: enabled, linked, inverted, fill rule, density, feather, bounds and components (subpaths in document px), or null. Read it before editing the path. |
|
|
317
|
+
| `add_vector_mask` | Layer › Vector Mask on any layer but a shape: `from` `path` (a `shape`, `subpaths` or `components`, like `add_shape_layer`), `reveal-all` or `hide-all` (empty path). Reveals inside the path, sharp at any size; it combines with the raster mask. Returns the vector mask. |
|
|
318
|
+
| `set_vector_mask_path` | Replace the vector mask's path (properties kept). Returns the vector mask. |
|
|
319
|
+
| `set_vector_mask_properties` | `enabled`, `linked` (false: stays put when the layer moves), `inverted`, `density`, `feather` px; the path is kept. Returns the vector mask. |
|
|
320
|
+
| `rasterize_vector_mask` | Multiply the path into the raster mask (adding one) and drop the vector mask, so it can be painted. Returns the mask summary. |
|
|
321
|
+
| `remove_vector_mask` | Delete the vector mask (the raster mask stays). |
|
|
315
322
|
| `convert_to_smart_object` | Convert sibling `layerIds` (default the active layer) to one smart object at the top one's position, optional `name`. One pixel layer keeps its id, look and properties (filters become smart filters); several layers, groups or adjustments nest as a layer document. Returns the `layer` and the `smartObject` summary. |
|
|
316
323
|
| `rasterize_smart_object` | Turn a smart object into a pixel layer holding what it shows now (smart filters baked; same id, mask, effects, opacity, blend). Destructive: the contents and filters are gone. Returns the layer. |
|
|
317
324
|
| `set_smart_object_transform` | Set a smart object's transform absolutely: `corners`, `matrix` (contents → document), or `scaleX` / `scaleY` (percent of the contents), `rotate`, `skewX`, `skewY`, `x`, `y` (where the contents' centre goes; unset numbers keep their values); `warp` preset or mesh in contents px, `null` removes it; `interpolation`. Re-renders from the contents. Returns `placement`, `masksMoved` and `bounds`. |
|