@pixerate/editor 0.183.0 → 0.186.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-Y46OMERN.js → chunk-FW7N64XK.js} +298 -189
- package/dist/{chunk-UHMSMUHK.cjs → chunk-X2KQQZBT.cjs} +358 -249
- package/dist/image-editor/controller.d.cts +208 -8
- package/dist/image-editor/controller.d.ts +208 -8
- package/dist/image-editor/index.cjs +2610 -1025
- package/dist/image-editor/index.js +1672 -87
- package/dist/image-editor/layers/model.d.cts +5 -1
- package/dist/image-editor/layers/model.d.ts +5 -1
- 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 +23 -1
- package/dist/image-editor/layers/panel.d.ts +23 -1
- package/dist/image-editor/layers/serialize.d.cts +3 -0
- package/dist/image-editor/layers/serialize.d.ts +3 -0
- package/dist/image-editor/psd/channels.d.cts +24 -0
- package/dist/image-editor/psd/channels.d.ts +24 -0
- package/dist/image-editor/psd/export.d.cts +3 -0
- package/dist/image-editor/psd/export.d.ts +3 -0
- package/dist/image-editor/psd/import.d.cts +10 -0
- package/dist/image-editor/psd/import.d.ts +10 -0
- package/dist/image-editor/renderer.d.cts +6 -0
- package/dist/image-editor/renderer.d.ts +6 -0
- package/dist/image-editor/selection/channels.d.cts +52 -0
- package/dist/image-editor/selection/channels.d.ts +52 -0
- package/dist/image-editor/selection/gesture.d.cts +47 -2
- package/dist/image-editor/selection/gesture.d.ts +47 -2
- package/dist/image-editor/selection/index.d.cts +2 -0
- package/dist/image-editor/selection/index.d.ts +2 -0
- package/dist/image-editor/selection/modify.d.cts +3 -2
- package/dist/image-editor/selection/modify.d.ts +3 -2
- package/dist/image-editor/selection/overlay.d.cts +2 -0
- package/dist/image-editor/selection/overlay.d.ts +2 -0
- package/dist/image-editor/selection/stroke.d.cts +8 -0
- package/dist/image-editor/selection/stroke.d.ts +8 -0
- package/dist/image-editor/selection/tool-options.d.cts +12 -2
- package/dist/image-editor/selection/tool-options.d.ts +12 -2
- package/dist/image-editor/selection/wand.d.cts +37 -0
- package/dist/image-editor/selection/wand.d.ts +37 -0
- package/dist/image-editor/selection-tools.d.cts +8 -3
- package/dist/image-editor/selection-tools.d.ts +8 -3
- package/dist/image-editor/tools.d.cts +10 -2
- package/dist/image-editor/tools.d.ts +10 -2
- package/dist/image-editor/types.d.cts +12 -0
- package/dist/image-editor/types.d.ts +12 -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 +19 -21
- package/skills/pixerate-image-editor/references/free-transform.md +22 -0
- package/skills/pixerate-image-selection-masking/SKILL.md +36 -3
|
@@ -474,7 +474,11 @@ export interface SmartObjectLayer extends LayerBase {
|
|
|
474
474
|
export type ImageLayer = PixelLayer | AdjustmentLayerNode | GroupLayer | AnnotationLayer | SmartObjectLayer | ShapeLayer | TypeLayer;
|
|
475
475
|
export type ImageLayerType = ImageLayer['type'];
|
|
476
476
|
/** Which part of the active layer painting targets (`filter-mask`: a smart object's filter mask). */
|
|
477
|
-
|
|
477
|
+
/**
|
|
478
|
+
* What a paint, fill or retouch writes: a layer's pixels, its mask, a smart object's filter mask,
|
|
479
|
+
* or (in Quick Mask mode) the selection itself (`quick-mask`, not a layer).
|
|
480
|
+
*/
|
|
481
|
+
export type LayerTarget = 'pixels' | 'mask' | 'filter-mask' | 'quick-mask';
|
|
478
482
|
/** A fresh id with `prefix` (`layer`, `flt`, …). */
|
|
479
483
|
export declare function newLayerId(prefix?: string): string;
|
|
480
484
|
export type LayerLocation = RasterLayerLocation<ImageLayer>;
|
|
@@ -474,7 +474,11 @@ export interface SmartObjectLayer extends LayerBase {
|
|
|
474
474
|
export type ImageLayer = PixelLayer | AdjustmentLayerNode | GroupLayer | AnnotationLayer | SmartObjectLayer | ShapeLayer | TypeLayer;
|
|
475
475
|
export type ImageLayerType = ImageLayer['type'];
|
|
476
476
|
/** Which part of the active layer painting targets (`filter-mask`: a smart object's filter mask). */
|
|
477
|
-
|
|
477
|
+
/**
|
|
478
|
+
* What a paint, fill or retouch writes: a layer's pixels, its mask, a smart object's filter mask,
|
|
479
|
+
* or (in Quick Mask mode) the selection itself (`quick-mask`, not a layer).
|
|
480
|
+
*/
|
|
481
|
+
export type LayerTarget = 'pixels' | 'mask' | 'filter-mask' | 'quick-mask';
|
|
478
482
|
/** A fresh id with `prefix` (`layer`, `flt`, …). */
|
|
479
483
|
export declare function newLayerId(prefix?: string): string;
|
|
480
484
|
export type LayerLocation = RasterLayerLocation<ImageLayer>;
|
|
@@ -139,7 +139,8 @@ export interface ShortcutEvent {
|
|
|
139
139
|
/**
|
|
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
|
-
* opacity to 10..90 % and 0 to 100 %; D resets the colours to black and white; X swaps them
|
|
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
144
|
*/
|
|
144
145
|
export declare function handlePaintShortcut(controller: ImageEditorController, e: ShortcutEvent): boolean;
|
|
145
146
|
/** One pointer sample in document pixels. */
|
|
@@ -139,7 +139,8 @@ export interface ShortcutEvent {
|
|
|
139
139
|
/**
|
|
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
|
-
* opacity to 10..90 % and 0 to 100 %; D resets the colours to black and white; X swaps them
|
|
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
144
|
*/
|
|
144
145
|
export declare function handlePaintShortcut(controller: ImageEditorController, e: ShortcutEvent): boolean;
|
|
145
146
|
/** One pointer sample in document pixels. */
|
|
@@ -6,6 +6,28 @@
|
|
|
6
6
|
import type { ImageEditorController } from '../controller.cjs';
|
|
7
7
|
import { type ImageLayer, type SmartFilter } from './model.cjs';
|
|
8
8
|
import type { LayerPlacement } from './ops.cjs';
|
|
9
|
+
/**
|
|
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), Shift-click turns the mask
|
|
12
|
+
* on or off, and a plain click makes the mask the paint target.
|
|
13
|
+
*/
|
|
14
|
+
export declare function maskThumbnailClick(controller: ImageEditorController, layer: ImageLayer, e: {
|
|
15
|
+
ctrlKey?: boolean;
|
|
16
|
+
metaKey?: boolean;
|
|
17
|
+
shiftKey?: boolean;
|
|
18
|
+
altKey?: boolean;
|
|
19
|
+
}): void;
|
|
20
|
+
/**
|
|
21
|
+
* A click on a layer's pixel thumbnail: Ctrl/⌘-click loads the layer's transparency as the
|
|
22
|
+
* selection (Shift adds, Alt subtracts, both intersect) and returns true; other clicks are left
|
|
23
|
+
* to the row (false).
|
|
24
|
+
*/
|
|
25
|
+
export declare function layerThumbnailClick(controller: ImageEditorController, layer: ImageLayer, e: {
|
|
26
|
+
ctrlKey?: boolean;
|
|
27
|
+
metaKey?: boolean;
|
|
28
|
+
shiftKey?: boolean;
|
|
29
|
+
altKey?: boolean;
|
|
30
|
+
}): boolean;
|
|
9
31
|
export interface LayerPanelRow {
|
|
10
32
|
layer: ImageLayer;
|
|
11
33
|
/** Nesting depth (0 = top level). */
|
|
@@ -34,7 +56,7 @@ export type DropZone = 'above' | 'below' | 'inside';
|
|
|
34
56
|
export declare function dropZone(fraction: number, isGroup: boolean): DropZone;
|
|
35
57
|
/** The placement for `move_layer` when `dragId` is dropped on row `targetId` in `zone`, or `null` for a no-op. */
|
|
36
58
|
export declare function dropPlacement(layers: readonly ImageLayer[], dragId: string, targetId: string, zone: DropZone): LayerPlacement | null;
|
|
37
|
-
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' | 'apply-mask' | 'delete-mask' | 'toggle-mask' | 'toggle-mask-link' | 'toggle-clip' | 'rasterize' | 'convert-smart' | 'edit-contents' | 'smart-via-copy' | 'add-filter-mask';
|
|
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';
|
|
38
60
|
export interface LayerMenuItem {
|
|
39
61
|
action: LayerMenuAction;
|
|
40
62
|
label: string;
|
|
@@ -6,6 +6,28 @@
|
|
|
6
6
|
import type { ImageEditorController } from '../controller.js';
|
|
7
7
|
import { type ImageLayer, type SmartFilter } from './model.js';
|
|
8
8
|
import type { LayerPlacement } from './ops.js';
|
|
9
|
+
/**
|
|
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), Shift-click turns the mask
|
|
12
|
+
* on or off, and a plain click makes the mask the paint target.
|
|
13
|
+
*/
|
|
14
|
+
export declare function maskThumbnailClick(controller: ImageEditorController, layer: ImageLayer, e: {
|
|
15
|
+
ctrlKey?: boolean;
|
|
16
|
+
metaKey?: boolean;
|
|
17
|
+
shiftKey?: boolean;
|
|
18
|
+
altKey?: boolean;
|
|
19
|
+
}): void;
|
|
20
|
+
/**
|
|
21
|
+
* A click on a layer's pixel thumbnail: Ctrl/⌘-click loads the layer's transparency as the
|
|
22
|
+
* selection (Shift adds, Alt subtracts, both intersect) and returns true; other clicks are left
|
|
23
|
+
* to the row (false).
|
|
24
|
+
*/
|
|
25
|
+
export declare function layerThumbnailClick(controller: ImageEditorController, layer: ImageLayer, e: {
|
|
26
|
+
ctrlKey?: boolean;
|
|
27
|
+
metaKey?: boolean;
|
|
28
|
+
shiftKey?: boolean;
|
|
29
|
+
altKey?: boolean;
|
|
30
|
+
}): boolean;
|
|
9
31
|
export interface LayerPanelRow {
|
|
10
32
|
layer: ImageLayer;
|
|
11
33
|
/** Nesting depth (0 = top level). */
|
|
@@ -34,7 +56,7 @@ export type DropZone = 'above' | 'below' | 'inside';
|
|
|
34
56
|
export declare function dropZone(fraction: number, isGroup: boolean): DropZone;
|
|
35
57
|
/** The placement for `move_layer` when `dragId` is dropped on row `targetId` in `zone`, or `null` for a no-op. */
|
|
36
58
|
export declare function dropPlacement(layers: readonly ImageLayer[], dragId: string, targetId: string, zone: DropZone): LayerPlacement | null;
|
|
37
|
-
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' | 'apply-mask' | 'delete-mask' | 'toggle-mask' | 'toggle-mask-link' | 'toggle-clip' | 'rasterize' | 'convert-smart' | 'edit-contents' | 'smart-via-copy' | 'add-filter-mask';
|
|
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';
|
|
38
60
|
export interface LayerMenuItem {
|
|
39
61
|
action: LayerMenuAction;
|
|
40
62
|
label: string;
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import type { Annotation, CropBox, DepthMaskOptions, ImageTransform } from '../types.cjs';
|
|
10
10
|
import type { SerializedSelection } from '../selection/mask.cjs';
|
|
11
|
+
import type { SerializedAlphaChannel } from '../selection/channels.cjs';
|
|
11
12
|
import type { SerializedColorMode, SerializedColorProfile } from '../color-management.cjs';
|
|
12
13
|
import { type PsdSmartFilter, type EffectSmartFilter, type ImageEffectGenerator, type SmartContents, type ImageLayer, type LayerFilter, type LayerLocks, type ShapeComponent, type ShapePaint, type ShapeStroke, type ParagraphRun, type TextRun, type TypeLayer } from './model.cjs';
|
|
13
14
|
import { type GlobalLight, type LayerEffect, type LayerEffects } from '../../raster/effects/model.cjs';
|
|
@@ -222,6 +223,8 @@ export interface SerializedLayeredImageEditorState {
|
|
|
222
223
|
/** Blur migrated from a v1 / v2 document with adjustment layers (runs after the layers). */
|
|
223
224
|
legacyOutputBlur?: number;
|
|
224
225
|
selection?: SerializedSelection;
|
|
226
|
+
/** Alpha channels (saved selections), run-length encoded. */
|
|
227
|
+
channels?: SerializedAlphaChannel[];
|
|
225
228
|
/** Global light for layer effects (missing = 120°, 30°). */
|
|
226
229
|
globalLight?: GlobalLight;
|
|
227
230
|
/** The document's patterns for pattern effects, each an RGBA PNG data URL. */
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import type { Annotation, CropBox, DepthMaskOptions, ImageTransform } from '../types.js';
|
|
10
10
|
import type { SerializedSelection } from '../selection/mask.js';
|
|
11
|
+
import type { SerializedAlphaChannel } from '../selection/channels.js';
|
|
11
12
|
import type { SerializedColorMode, SerializedColorProfile } from '../color-management.js';
|
|
12
13
|
import { type PsdSmartFilter, type EffectSmartFilter, type ImageEffectGenerator, type SmartContents, type ImageLayer, type LayerFilter, type LayerLocks, type ShapeComponent, type ShapePaint, type ShapeStroke, type ParagraphRun, type TextRun, type TypeLayer } from './model.js';
|
|
13
14
|
import { type GlobalLight, type LayerEffect, type LayerEffects } from '../../raster/effects/model.js';
|
|
@@ -222,6 +223,8 @@ export interface SerializedLayeredImageEditorState {
|
|
|
222
223
|
/** Blur migrated from a v1 / v2 document with adjustment layers (runs after the layers). */
|
|
223
224
|
legacyOutputBlur?: number;
|
|
224
225
|
selection?: SerializedSelection;
|
|
226
|
+
/** Alpha channels (saved selections), run-length encoded. */
|
|
227
|
+
channels?: SerializedAlphaChannel[];
|
|
225
228
|
/** Global light for layer effects (missing = 120°, 30°). */
|
|
226
229
|
globalLight?: GlobalLight;
|
|
227
230
|
/** The document's patterns for pattern effects, each an RGBA PNG data URL. */
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { PsdResource } from './file.cjs';
|
|
2
|
+
/** An alpha channel as the PSD code reads and writes it: an 8-bit plane over the canvas. */
|
|
3
|
+
export interface PsdAlphaChannel {
|
|
4
|
+
name: string;
|
|
5
|
+
/** `width × height` coverage, 255 = selected. */
|
|
6
|
+
data: Uint8Array;
|
|
7
|
+
/** `#rrggbb` overlay colour. */
|
|
8
|
+
color: string;
|
|
9
|
+
/** 0..1. */
|
|
10
|
+
opacity: number;
|
|
11
|
+
indicates: 'masked' | 'selected';
|
|
12
|
+
}
|
|
13
|
+
/** The image resources that name and describe `channels`. */
|
|
14
|
+
export declare function alphaChannelResources(channels: readonly PsdAlphaChannel[]): PsdResource[];
|
|
15
|
+
/**
|
|
16
|
+
* The alpha channels of a file: merged planes `first … channels − 1`, named from 1045 (or
|
|
17
|
+
* 1006), described by 1077. Spot colour channels (kind 2) are left out and reported.
|
|
18
|
+
*/
|
|
19
|
+
export declare function readAlphaChannels(planes: Uint8Array, header: {
|
|
20
|
+
width: number;
|
|
21
|
+
height: number;
|
|
22
|
+
depth: number;
|
|
23
|
+
channels: number;
|
|
24
|
+
}, first: number, resource: (id: number) => Uint8Array | undefined, warn: (message: string) => void): PsdAlphaChannel[];
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { PsdResource } from './file.js';
|
|
2
|
+
/** An alpha channel as the PSD code reads and writes it: an 8-bit plane over the canvas. */
|
|
3
|
+
export interface PsdAlphaChannel {
|
|
4
|
+
name: string;
|
|
5
|
+
/** `width × height` coverage, 255 = selected. */
|
|
6
|
+
data: Uint8Array;
|
|
7
|
+
/** `#rrggbb` overlay colour. */
|
|
8
|
+
color: string;
|
|
9
|
+
/** 0..1. */
|
|
10
|
+
opacity: number;
|
|
11
|
+
indicates: 'masked' | 'selected';
|
|
12
|
+
}
|
|
13
|
+
/** The image resources that name and describe `channels`. */
|
|
14
|
+
export declare function alphaChannelResources(channels: readonly PsdAlphaChannel[]): PsdResource[];
|
|
15
|
+
/**
|
|
16
|
+
* The alpha channels of a file: merged planes `first … channels − 1`, named from 1045 (or
|
|
17
|
+
* 1006), described by 1077. Spot colour channels (kind 2) are left out and reported.
|
|
18
|
+
*/
|
|
19
|
+
export declare function readAlphaChannels(planes: Uint8Array, header: {
|
|
20
|
+
width: number;
|
|
21
|
+
height: number;
|
|
22
|
+
depth: number;
|
|
23
|
+
channels: number;
|
|
24
|
+
}, first: number, resource: (id: number) => Uint8Array | undefined, warn: (message: string) => void): PsdAlphaChannel[];
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type ImageLayer, type SmartContents } from '../layers/model.cjs';
|
|
2
|
+
import { type PsdAlphaChannel } from './channels.cjs';
|
|
2
3
|
import { type GlobalLight } from '../../raster/effects/model.cjs';
|
|
3
4
|
import { type EffectPattern } from '../../raster/effects/patterns.cjs';
|
|
4
5
|
export interface PsdExportInput {
|
|
@@ -8,6 +9,8 @@ export interface PsdExportInput {
|
|
|
8
9
|
layers: readonly ImageLayer[];
|
|
9
10
|
/** The composite, `width × height` RGBA, written as the merged image. */
|
|
10
11
|
merged: ArrayLike<number>;
|
|
12
|
+
/** Alpha channels, written as extra merged planes with their names and display info. */
|
|
13
|
+
alphaChannels?: readonly PsdAlphaChannel[];
|
|
11
14
|
/** Pixels per inch (default 72). */
|
|
12
15
|
resolution?: number;
|
|
13
16
|
/** The document's patterns; those the effects use are embedded (built-in ones too). */
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type ImageLayer, type SmartContents } from '../layers/model.js';
|
|
2
|
+
import { type PsdAlphaChannel } from './channels.js';
|
|
2
3
|
import { type GlobalLight } from '../../raster/effects/model.js';
|
|
3
4
|
import { type EffectPattern } from '../../raster/effects/patterns.js';
|
|
4
5
|
export interface PsdExportInput {
|
|
@@ -8,6 +9,8 @@ export interface PsdExportInput {
|
|
|
8
9
|
layers: readonly ImageLayer[];
|
|
9
10
|
/** The composite, `width × height` RGBA, written as the merged image. */
|
|
10
11
|
merged: ArrayLike<number>;
|
|
12
|
+
/** Alpha channels, written as extra merged planes with their names and display info. */
|
|
13
|
+
alphaChannels?: readonly PsdAlphaChannel[];
|
|
11
14
|
/** Pixels per inch (default 72). */
|
|
12
15
|
resolution?: number;
|
|
13
16
|
/** The document's patterns; those the effects use are embedded (built-in ones too). */
|
|
@@ -1,3 +1,11 @@
|
|
|
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
|
+
import { type PsdAlphaChannel } from './channels.cjs';
|
|
1
9
|
import type { ImageLayer, LayerBlendMode } from '../layers/model.cjs';
|
|
2
10
|
import { type PsdFile } from './file.cjs';
|
|
3
11
|
import type { DocumentColorProfile } from '../color-management.cjs';
|
|
@@ -54,6 +62,8 @@ export interface PsdImportResult {
|
|
|
54
62
|
};
|
|
55
63
|
/** The bits per channel the layers keep: 16 or 32 for such files (not indexed or bitmap), else 8. */
|
|
56
64
|
bitDepth: 8 | 16 | 32;
|
|
65
|
+
/** The file's alpha channels (saved selections), as 8-bit planes. */
|
|
66
|
+
alphaChannels?: PsdAlphaChannel[];
|
|
57
67
|
}
|
|
58
68
|
export interface PsdImportOptions {
|
|
59
69
|
/** Makes layer ids (defaults to `psd-<n>`). */
|
|
@@ -1,3 +1,11 @@
|
|
|
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
|
+
import { type PsdAlphaChannel } from './channels.js';
|
|
1
9
|
import type { ImageLayer, LayerBlendMode } from '../layers/model.js';
|
|
2
10
|
import { type PsdFile } from './file.js';
|
|
3
11
|
import type { DocumentColorProfile } from '../color-management.js';
|
|
@@ -54,6 +62,8 @@ export interface PsdImportResult {
|
|
|
54
62
|
};
|
|
55
63
|
/** The bits per channel the layers keep: 16 or 32 for such files (not indexed or bitmap), else 8. */
|
|
56
64
|
bitDepth: 8 | 16 | 32;
|
|
65
|
+
/** The file's alpha channels (saved selections), as 8-bit planes. */
|
|
66
|
+
alphaChannels?: PsdAlphaChannel[];
|
|
57
67
|
}
|
|
58
68
|
export interface PsdImportOptions {
|
|
59
69
|
/** Makes layer ids (defaults to `psd-<n>`). */
|
|
@@ -174,6 +174,12 @@ export declare class ImageEditorRenderer {
|
|
|
174
174
|
private publishHistogram;
|
|
175
175
|
private quickMaskCache;
|
|
176
176
|
private outlineCache;
|
|
177
|
+
private emptyMaskCache;
|
|
178
|
+
/** An empty selection of the image's size (Quick Mask mode with nothing selected). */
|
|
179
|
+
private emptyMask;
|
|
180
|
+
private overlayCache;
|
|
181
|
+
/** A channel's tint (colour, opacity, masked or selected area), drawn in natural image space. */
|
|
182
|
+
private drawMaskOverlay;
|
|
177
183
|
/** Rubylith over the unselected area, drawn in natural image space. */
|
|
178
184
|
private drawQuickMask;
|
|
179
185
|
/**
|
|
@@ -174,6 +174,12 @@ export declare class ImageEditorRenderer {
|
|
|
174
174
|
private publishHistogram;
|
|
175
175
|
private quickMaskCache;
|
|
176
176
|
private outlineCache;
|
|
177
|
+
private emptyMaskCache;
|
|
178
|
+
/** An empty selection of the image's size (Quick Mask mode with nothing selected). */
|
|
179
|
+
private emptyMask;
|
|
180
|
+
private overlayCache;
|
|
181
|
+
/** A channel's tint (colour, opacity, masked or selected area), drawn in natural image space. */
|
|
182
|
+
private drawMaskOverlay;
|
|
177
183
|
/** Rubylith over the unselected area, drawn in natural image space. */
|
|
178
184
|
private drawQuickMask;
|
|
179
185
|
/**
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { type SelectionMask, type SerializedSelection } from './mask.cjs';
|
|
2
|
+
/**
|
|
3
|
+
* An alpha channel: a saved selection kept with the document (Select › Save Selection), shown
|
|
4
|
+
* as a tinted overlay when visible. Its mask is the selection's 8-bit coverage over the canvas
|
|
5
|
+
* (immutable, so undo steps share it).
|
|
6
|
+
*/
|
|
7
|
+
export interface AlphaChannel {
|
|
8
|
+
id: string;
|
|
9
|
+
name: string;
|
|
10
|
+
/** Coverage (255 = selected). An empty channel has a mask with `bounds: null`. */
|
|
11
|
+
mask: SelectionMask;
|
|
12
|
+
/** Overlay tint, `#rrggbb` (default red, the Quick Mask's). */
|
|
13
|
+
color: string;
|
|
14
|
+
/** Overlay opacity 0..1 (default 0.5). */
|
|
15
|
+
opacity: number;
|
|
16
|
+
/** Whether the tint covers the `masked` (unselected, default) or the `selected` area. */
|
|
17
|
+
indicates: 'masked' | 'selected';
|
|
18
|
+
/** Shown as an overlay on the canvas (default false). */
|
|
19
|
+
visible: boolean;
|
|
20
|
+
}
|
|
21
|
+
/** An alpha channel as stored in a document. */
|
|
22
|
+
export interface SerializedAlphaChannel extends Omit<AlphaChannel, 'mask'> {
|
|
23
|
+
mask: SerializedSelection;
|
|
24
|
+
}
|
|
25
|
+
export declare const DEFAULT_CHANNEL_COLOR = "#ff0000";
|
|
26
|
+
/** A summary of a channel for agents and panels (no pixels). */
|
|
27
|
+
export declare function describeChannel(channel: AlphaChannel): {
|
|
28
|
+
bounds: import("../index.cjs").CropBox | null;
|
|
29
|
+
percent: number;
|
|
30
|
+
id: string;
|
|
31
|
+
name: string;
|
|
32
|
+
/** Overlay tint, `#rrggbb` (default red, the Quick Mask's). */
|
|
33
|
+
color: string;
|
|
34
|
+
/** Overlay opacity 0..1 (default 0.5). */
|
|
35
|
+
opacity: number;
|
|
36
|
+
/** Whether the tint covers the `masked` (unselected, default) or the `selected` area. */
|
|
37
|
+
indicates: "masked" | "selected";
|
|
38
|
+
/** Shown as an overlay on the canvas (default false). */
|
|
39
|
+
visible: boolean;
|
|
40
|
+
};
|
|
41
|
+
export declare function serializeChannels(channels: readonly AlphaChannel[]): SerializedAlphaChannel[];
|
|
42
|
+
/** Restores stored channels, skipping (and reporting) damaged ones or ones of another size. */
|
|
43
|
+
export declare function deserializeChannels(value: unknown, size: {
|
|
44
|
+
width: number;
|
|
45
|
+
height: number;
|
|
46
|
+
}, problems?: string[]): AlphaChannel[];
|
|
47
|
+
/** A channel's grey thumbnail (white = selected) as RGBA pixels, at most `maxSide` px. */
|
|
48
|
+
export declare function channelThumbnail(channel: AlphaChannel, maxSide?: number): {
|
|
49
|
+
width: number;
|
|
50
|
+
height: number;
|
|
51
|
+
data: Uint8ClampedArray;
|
|
52
|
+
};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { type SelectionMask, type SerializedSelection } from './mask.js';
|
|
2
|
+
/**
|
|
3
|
+
* An alpha channel: a saved selection kept with the document (Select › Save Selection), shown
|
|
4
|
+
* as a tinted overlay when visible. Its mask is the selection's 8-bit coverage over the canvas
|
|
5
|
+
* (immutable, so undo steps share it).
|
|
6
|
+
*/
|
|
7
|
+
export interface AlphaChannel {
|
|
8
|
+
id: string;
|
|
9
|
+
name: string;
|
|
10
|
+
/** Coverage (255 = selected). An empty channel has a mask with `bounds: null`. */
|
|
11
|
+
mask: SelectionMask;
|
|
12
|
+
/** Overlay tint, `#rrggbb` (default red, the Quick Mask's). */
|
|
13
|
+
color: string;
|
|
14
|
+
/** Overlay opacity 0..1 (default 0.5). */
|
|
15
|
+
opacity: number;
|
|
16
|
+
/** Whether the tint covers the `masked` (unselected, default) or the `selected` area. */
|
|
17
|
+
indicates: 'masked' | 'selected';
|
|
18
|
+
/** Shown as an overlay on the canvas (default false). */
|
|
19
|
+
visible: boolean;
|
|
20
|
+
}
|
|
21
|
+
/** An alpha channel as stored in a document. */
|
|
22
|
+
export interface SerializedAlphaChannel extends Omit<AlphaChannel, 'mask'> {
|
|
23
|
+
mask: SerializedSelection;
|
|
24
|
+
}
|
|
25
|
+
export declare const DEFAULT_CHANNEL_COLOR = "#ff0000";
|
|
26
|
+
/** A summary of a channel for agents and panels (no pixels). */
|
|
27
|
+
export declare function describeChannel(channel: AlphaChannel): {
|
|
28
|
+
bounds: import("../index.js").CropBox | null;
|
|
29
|
+
percent: number;
|
|
30
|
+
id: string;
|
|
31
|
+
name: string;
|
|
32
|
+
/** Overlay tint, `#rrggbb` (default red, the Quick Mask's). */
|
|
33
|
+
color: string;
|
|
34
|
+
/** Overlay opacity 0..1 (default 0.5). */
|
|
35
|
+
opacity: number;
|
|
36
|
+
/** Whether the tint covers the `masked` (unselected, default) or the `selected` area. */
|
|
37
|
+
indicates: "masked" | "selected";
|
|
38
|
+
/** Shown as an overlay on the canvas (default false). */
|
|
39
|
+
visible: boolean;
|
|
40
|
+
};
|
|
41
|
+
export declare function serializeChannels(channels: readonly AlphaChannel[]): SerializedAlphaChannel[];
|
|
42
|
+
/** Restores stored channels, skipping (and reporting) damaged ones or ones of another size. */
|
|
43
|
+
export declare function deserializeChannels(value: unknown, size: {
|
|
44
|
+
width: number;
|
|
45
|
+
height: number;
|
|
46
|
+
}, problems?: string[]): AlphaChannel[];
|
|
47
|
+
/** A channel's grey thumbnail (white = selected) as RGBA pixels, at most `maxSide` px. */
|
|
48
|
+
export declare function channelThumbnail(channel: AlphaChannel, maxSide?: number): {
|
|
49
|
+
width: number;
|
|
50
|
+
height: number;
|
|
51
|
+
data: Uint8ClampedArray;
|
|
52
|
+
};
|
|
@@ -4,14 +4,26 @@ import { type SelectionToolOptions } from './tool-options.cjs';
|
|
|
4
4
|
export interface GestureModifiers {
|
|
5
5
|
shiftKey?: boolean;
|
|
6
6
|
altKey?: boolean;
|
|
7
|
+
/** The click count of a mouse event (2 on a double-click). */
|
|
8
|
+
detail?: number;
|
|
7
9
|
}
|
|
10
|
+
/** `point` moved onto the nearest 45° ray from `from` (Shift with the polygonal lasso). */
|
|
11
|
+
export declare function snapTo45(from: ImagePoint, point: ImagePoint): ImagePoint;
|
|
8
12
|
/**
|
|
9
13
|
* Pointer gestures of the selection tools, shared by the React and Svelte image editors: feed
|
|
10
14
|
* it pointer positions in natural image pixels (`canvasToImagePoint(..., false)`).
|
|
11
15
|
*
|
|
12
16
|
* - Magic wand: selects on `begin` (async, as it may read pixels).
|
|
17
|
+
* - Color Range: on `begin`, samples the colour under the pointer and selects every similar pixel
|
|
18
|
+
* (with the modifiers, Shift-click adds a colour and Alt-click removes one, as the + and −
|
|
19
|
+
* eyedroppers).
|
|
13
20
|
* - Rectangle / ellipse: drag a box; a click without a drag deselects (replace mode).
|
|
14
21
|
* - Lasso: drag a free-hand path, closed on `end`.
|
|
22
|
+
* - Polygonal lasso: each click adds a corner (Shift: on a 45° ray from the last one), dragging
|
|
23
|
+
* adds a free-hand stretch; a double-click, a click on the first corner or Enter (`key`)
|
|
24
|
+
* closes it, Backspace removes the last corner and Escape cancels. It stays `active` between
|
|
25
|
+
* clicks, so feed it pointer moves without a button too.
|
|
26
|
+
* - Single row / column: a click selects a 1 px line across the image.
|
|
15
27
|
*
|
|
16
28
|
* Shift adds, Alt subtracts, both intersect (overriding the options bar mode). While dragging,
|
|
17
29
|
* {@link draftPath} is the outline to show (`RenderOptions.draftSelectionPath`).
|
|
@@ -23,6 +35,12 @@ export declare class SelectionGesture {
|
|
|
23
35
|
private points;
|
|
24
36
|
private current;
|
|
25
37
|
private modifiers;
|
|
38
|
+
/** Polygonal lasso corners while one is being drawn. */
|
|
39
|
+
private polygon;
|
|
40
|
+
private pressedAt;
|
|
41
|
+
private freehand;
|
|
42
|
+
/** A click this close to the first corner (natural pixels) closes a polygonal lasso. */
|
|
43
|
+
closeRadius: number;
|
|
26
44
|
/** The last error (e.g. pixels unavailable for the wand), for the UI to show. */
|
|
27
45
|
error: string | null;
|
|
28
46
|
constructor(controller: ImageEditorController, getOptions: () => SelectionToolOptions);
|
|
@@ -32,9 +50,36 @@ export declare class SelectionGesture {
|
|
|
32
50
|
/** Pointer down. Resolves once a wand click has been applied. */
|
|
33
51
|
begin(point: ImagePoint, modifiers?: GestureModifiers): Promise<void>;
|
|
34
52
|
/** Pointer move; returns true when the draft changed (re-render). */
|
|
35
|
-
move(point: ImagePoint): boolean;
|
|
53
|
+
move(point: ImagePoint, modifiers?: GestureModifiers): boolean;
|
|
36
54
|
/** Pointer up: commits the shape. Returns true when the selection changed. */
|
|
37
55
|
end(point?: ImagePoint, modifiers?: GestureModifiers): boolean;
|
|
38
|
-
/**
|
|
56
|
+
/** Closes a polygonal lasso and selects it. Returns true when the selection changed. */
|
|
57
|
+
close(): boolean;
|
|
58
|
+
/**
|
|
59
|
+
* Keys for a polygonal lasso being drawn: Enter closes it, Escape cancels, Backspace / Delete
|
|
60
|
+
* removes the last corner. Returns true when the key was used (the host prevents its default).
|
|
61
|
+
*/
|
|
62
|
+
key(key: string): boolean;
|
|
63
|
+
/** Abandons a drag (or a polygonal lasso) without changing the selection. */
|
|
39
64
|
cancel(): void;
|
|
40
65
|
}
|
|
66
|
+
/**
|
|
67
|
+
* Edit shortcuts in select mode, as in Photoshop: Ctrl/⌘+C copies (with Shift, Copy Merged),
|
|
68
|
+
* Ctrl/⌘+X cuts, Ctrl/⌘+V pastes (with Shift, in place; with Alt+Shift, into the selection),
|
|
69
|
+
* Ctrl/⌘+D deselects, Ctrl/⌘+Shift+D reselects and Ctrl/⌘+Shift+I inverts. Returns true when
|
|
70
|
+
* the key was used (the host prevents its default); errors go to `onError`.
|
|
71
|
+
*/
|
|
72
|
+
export declare function handleSelectionShortcut(controller: ImageEditorController, e: {
|
|
73
|
+
key: string;
|
|
74
|
+
ctrlKey?: boolean;
|
|
75
|
+
metaKey?: boolean;
|
|
76
|
+
shiftKey?: boolean;
|
|
77
|
+
altKey?: boolean;
|
|
78
|
+
}, onError?: (message: string) => void): boolean;
|
|
79
|
+
/** Q (no modifiers) toggles Quick Mask mode. Returns true when the key was used. */
|
|
80
|
+
export declare function handleQuickMaskKey(controller: ImageEditorController, e: {
|
|
81
|
+
key: string;
|
|
82
|
+
ctrlKey?: boolean;
|
|
83
|
+
metaKey?: boolean;
|
|
84
|
+
altKey?: boolean;
|
|
85
|
+
}): boolean;
|
|
@@ -4,14 +4,26 @@ import { type SelectionToolOptions } from './tool-options.js';
|
|
|
4
4
|
export interface GestureModifiers {
|
|
5
5
|
shiftKey?: boolean;
|
|
6
6
|
altKey?: boolean;
|
|
7
|
+
/** The click count of a mouse event (2 on a double-click). */
|
|
8
|
+
detail?: number;
|
|
7
9
|
}
|
|
10
|
+
/** `point` moved onto the nearest 45° ray from `from` (Shift with the polygonal lasso). */
|
|
11
|
+
export declare function snapTo45(from: ImagePoint, point: ImagePoint): ImagePoint;
|
|
8
12
|
/**
|
|
9
13
|
* Pointer gestures of the selection tools, shared by the React and Svelte image editors: feed
|
|
10
14
|
* it pointer positions in natural image pixels (`canvasToImagePoint(..., false)`).
|
|
11
15
|
*
|
|
12
16
|
* - Magic wand: selects on `begin` (async, as it may read pixels).
|
|
17
|
+
* - Color Range: on `begin`, samples the colour under the pointer and selects every similar pixel
|
|
18
|
+
* (with the modifiers, Shift-click adds a colour and Alt-click removes one, as the + and −
|
|
19
|
+
* eyedroppers).
|
|
13
20
|
* - Rectangle / ellipse: drag a box; a click without a drag deselects (replace mode).
|
|
14
21
|
* - Lasso: drag a free-hand path, closed on `end`.
|
|
22
|
+
* - Polygonal lasso: each click adds a corner (Shift: on a 45° ray from the last one), dragging
|
|
23
|
+
* adds a free-hand stretch; a double-click, a click on the first corner or Enter (`key`)
|
|
24
|
+
* closes it, Backspace removes the last corner and Escape cancels. It stays `active` between
|
|
25
|
+
* clicks, so feed it pointer moves without a button too.
|
|
26
|
+
* - Single row / column: a click selects a 1 px line across the image.
|
|
15
27
|
*
|
|
16
28
|
* Shift adds, Alt subtracts, both intersect (overriding the options bar mode). While dragging,
|
|
17
29
|
* {@link draftPath} is the outline to show (`RenderOptions.draftSelectionPath`).
|
|
@@ -23,6 +35,12 @@ export declare class SelectionGesture {
|
|
|
23
35
|
private points;
|
|
24
36
|
private current;
|
|
25
37
|
private modifiers;
|
|
38
|
+
/** Polygonal lasso corners while one is being drawn. */
|
|
39
|
+
private polygon;
|
|
40
|
+
private pressedAt;
|
|
41
|
+
private freehand;
|
|
42
|
+
/** A click this close to the first corner (natural pixels) closes a polygonal lasso. */
|
|
43
|
+
closeRadius: number;
|
|
26
44
|
/** The last error (e.g. pixels unavailable for the wand), for the UI to show. */
|
|
27
45
|
error: string | null;
|
|
28
46
|
constructor(controller: ImageEditorController, getOptions: () => SelectionToolOptions);
|
|
@@ -32,9 +50,36 @@ export declare class SelectionGesture {
|
|
|
32
50
|
/** Pointer down. Resolves once a wand click has been applied. */
|
|
33
51
|
begin(point: ImagePoint, modifiers?: GestureModifiers): Promise<void>;
|
|
34
52
|
/** Pointer move; returns true when the draft changed (re-render). */
|
|
35
|
-
move(point: ImagePoint): boolean;
|
|
53
|
+
move(point: ImagePoint, modifiers?: GestureModifiers): boolean;
|
|
36
54
|
/** Pointer up: commits the shape. Returns true when the selection changed. */
|
|
37
55
|
end(point?: ImagePoint, modifiers?: GestureModifiers): boolean;
|
|
38
|
-
/**
|
|
56
|
+
/** Closes a polygonal lasso and selects it. Returns true when the selection changed. */
|
|
57
|
+
close(): boolean;
|
|
58
|
+
/**
|
|
59
|
+
* Keys for a polygonal lasso being drawn: Enter closes it, Escape cancels, Backspace / Delete
|
|
60
|
+
* removes the last corner. Returns true when the key was used (the host prevents its default).
|
|
61
|
+
*/
|
|
62
|
+
key(key: string): boolean;
|
|
63
|
+
/** Abandons a drag (or a polygonal lasso) without changing the selection. */
|
|
39
64
|
cancel(): void;
|
|
40
65
|
}
|
|
66
|
+
/**
|
|
67
|
+
* Edit shortcuts in select mode, as in Photoshop: Ctrl/⌘+C copies (with Shift, Copy Merged),
|
|
68
|
+
* Ctrl/⌘+X cuts, Ctrl/⌘+V pastes (with Shift, in place; with Alt+Shift, into the selection),
|
|
69
|
+
* Ctrl/⌘+D deselects, Ctrl/⌘+Shift+D reselects and Ctrl/⌘+Shift+I inverts. Returns true when
|
|
70
|
+
* the key was used (the host prevents its default); errors go to `onError`.
|
|
71
|
+
*/
|
|
72
|
+
export declare function handleSelectionShortcut(controller: ImageEditorController, e: {
|
|
73
|
+
key: string;
|
|
74
|
+
ctrlKey?: boolean;
|
|
75
|
+
metaKey?: boolean;
|
|
76
|
+
shiftKey?: boolean;
|
|
77
|
+
altKey?: boolean;
|
|
78
|
+
}, onError?: (message: string) => void): boolean;
|
|
79
|
+
/** Q (no modifiers) toggles Quick Mask mode. Returns true when the key was used. */
|
|
80
|
+
export declare function handleQuickMaskKey(controller: ImageEditorController, e: {
|
|
81
|
+
key: string;
|
|
82
|
+
ctrlKey?: boolean;
|
|
83
|
+
metaKey?: boolean;
|
|
84
|
+
altKey?: boolean;
|
|
85
|
+
}): boolean;
|
|
@@ -31,7 +31,8 @@ export declare function greyMorphology(src: ArrayLike<number>, w: number, h: num
|
|
|
31
31
|
* use one morphology, the remainder blends with the next pixel, so 0.3 px differs from 1 px.
|
|
32
32
|
*/
|
|
33
33
|
export declare function shiftCoverage(src: ArrayLike<number>, w: number, h: number, amount: number): Float32Array;
|
|
34
|
-
|
|
34
|
+
/** `expand` / `contract` are Photoshop's names; `grow` / `shrink` are the same operations, kept as aliases. */
|
|
35
|
+
export type SelectionModifyOp = 'expand' | 'contract' | 'grow' | 'shrink' | 'feather' | 'border' | 'smooth';
|
|
35
36
|
export declare const SELECTION_MODIFY_OPS: readonly SelectionModifyOp[];
|
|
36
|
-
/** Select › Modify (
|
|
37
|
+
/** Select › Modify (expand, contract, feather, border, smooth; grow and shrink are aliases) by `radius` pixels. */
|
|
37
38
|
export declare function modifySelection(mask: SelectionMask, op: SelectionModifyOp, radius: number): SelectionMask;
|
|
@@ -31,7 +31,8 @@ export declare function greyMorphology(src: ArrayLike<number>, w: number, h: num
|
|
|
31
31
|
* use one morphology, the remainder blends with the next pixel, so 0.3 px differs from 1 px.
|
|
32
32
|
*/
|
|
33
33
|
export declare function shiftCoverage(src: ArrayLike<number>, w: number, h: number, amount: number): Float32Array;
|
|
34
|
-
|
|
34
|
+
/** `expand` / `contract` are Photoshop's names; `grow` / `shrink` are the same operations, kept as aliases. */
|
|
35
|
+
export type SelectionModifyOp = 'expand' | 'contract' | 'grow' | 'shrink' | 'feather' | 'border' | 'smooth';
|
|
35
36
|
export declare const SELECTION_MODIFY_OPS: readonly SelectionModifyOp[];
|
|
36
|
-
/** Select › Modify (
|
|
37
|
+
/** Select › Modify (expand, contract, feather, border, smooth; grow and shrink are aliases) by `radius` pixels. */
|
|
37
38
|
export declare function modifySelection(mask: SelectionMask, op: SelectionModifyOp, radius: number): SelectionMask;
|
|
@@ -10,6 +10,8 @@ export interface QuickMaskStyle {
|
|
|
10
10
|
color?: readonly [number, number, number];
|
|
11
11
|
/** 0..1 (default 0.5): opacity over fully unselected pixels. */
|
|
12
12
|
opacity?: number;
|
|
13
|
+
/** Tint the unselected area (`masked`, default) or the selected area (`selected`). */
|
|
14
|
+
indicates?: 'masked' | 'selected';
|
|
13
15
|
}
|
|
14
16
|
/**
|
|
15
17
|
* Quick Mask view: RGBA pixels (natural image size) tinting the *unselected* area, so the
|