@pixerate/editor 0.103.0 → 0.105.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/THIRD_PARTY_NOTICES.md +2 -0
- package/dist/{chunk-NQLQ2JOI.js → chunk-4X5MIVCE.js} +1155 -295
- package/dist/chunk-4X5MIVCE.js.map +1 -0
- package/dist/{chunk-VSMM7B3P.cjs → chunk-ZID226ZG.cjs} +1169 -309
- package/dist/chunk-ZID226ZG.cjs.map +1 -0
- package/dist/{compositor-CTMU-B1t.d.cts → compositor-Bc3PNP3C.d.cts} +1 -1
- package/dist/{compositor-B1ZrKR89.d.ts → compositor-BsYYllvR.d.ts} +1 -1
- package/dist/{export-X9rY79p0.d.cts → export-_m3Es4ru.d.cts} +19 -4
- package/dist/{export-BLpMyCYg.d.ts → export-iMrop3Jm.d.ts} +19 -4
- package/dist/image-editor/index.cjs +523 -539
- package/dist/image-editor/index.cjs.map +1 -1
- package/dist/image-editor/index.d.cts +16 -8
- package/dist/image-editor/index.d.ts +16 -8
- package/dist/image-editor/index.js +37 -53
- package/dist/image-editor/index.js.map +1 -1
- package/dist/{mixer-DGcH6HLu.d.cts → mixer-C1M1Nua_.d.cts} +1 -1
- package/dist/{mixer-DG_9Yu2W.d.ts → mixer-Cu5a9Bzd.d.ts} +1 -1
- package/dist/paint/index.d.cts +2 -2
- package/dist/paint/index.d.ts +2 -2
- package/dist/paint-editor/index.cjs +1531 -128
- package/dist/paint-editor/index.cjs.map +1 -1
- package/dist/paint-editor/index.d.cts +461 -14
- package/dist/paint-editor/index.d.ts +461 -14
- package/dist/paint-editor/index.js +1479 -76
- package/dist/paint-editor/index.js.map +1 -1
- package/dist/raster/index.d.cts +4 -4
- package/dist/raster/index.d.ts +4 -4
- package/dist/{surface-AfHCH7BR.d.cts → surface-BBJN9wxg.d.cts} +1 -1
- package/dist/{surface-AfHCH7BR.d.ts → surface-BBJN9wxg.d.ts} +1 -1
- package/package.json +1 -1
- package/skills/pixerate-image-editor/SKILL.md +14 -5
- package/skills/pixerate-paint-editor/SKILL.md +49 -8
- package/dist/chunk-NQLQ2JOI.js.map +0 -1
- package/dist/chunk-VSMM7B3P.cjs.map +0 -1
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { R as RasterLayer, a as RasterGroupLayer, b as RasterPixelLayer, C as CompositorLayer, c as RasterCompositor, d as RasterSources, L as LayerLocks } from '../compositor-
|
|
2
|
-
import { B as BrushSettings, M as MixerSettings, C as CoverageMap, D as Dab, S as StrokePoint, a as MixerLoad } from '../mixer-
|
|
3
|
-
export { b as MAX_BRUSH_SIZE } from '../mixer-
|
|
4
|
-
import { R as RasterRect, a as TiledSurface, B as BlendMode } from '../surface-
|
|
5
|
-
export { b as Tile } from '../surface-
|
|
6
|
-
import { I as ImageEditorAssetStore, S as SerializedLayer, P as PsdExportResult } from '../export-
|
|
1
|
+
import { R as RasterLayer, a as RasterGroupLayer, b as RasterPixelLayer, C as CompositorLayer, c as RasterCompositor, d as RasterSources, L as LayerLocks } from '../compositor-BsYYllvR.js';
|
|
2
|
+
import { B as BrushSettings, M as MixerSettings, C as CoverageMap, D as Dab, S as StrokePoint, a as MixerLoad } from '../mixer-Cu5a9Bzd.js';
|
|
3
|
+
export { b as MAX_BRUSH_SIZE } from '../mixer-Cu5a9Bzd.js';
|
|
4
|
+
import { R as RasterRect, a as TiledSurface, B as BlendMode } from '../surface-BBJN9wxg.js';
|
|
5
|
+
export { b as BLEND_MODES, c as Tile, i as isBlendMode } from '../surface-BBJN9wxg.js';
|
|
6
|
+
import { I as ImageEditorAssetStore, S as SerializedLayer, P as PsdExportResult } from '../export-iMrop3Jm.js';
|
|
7
7
|
import { a as AgentToolProvider } from '../registry-D-4fit9C.js';
|
|
8
8
|
import '../types-CwMPoRMU.js';
|
|
9
9
|
import '../warp-CWHZzE3x.js';
|
|
@@ -203,12 +203,14 @@ interface PaintBrush {
|
|
|
203
203
|
}
|
|
204
204
|
declare function normalizeDynamics(raw?: Partial<BrushDynamics>, base?: BrushDynamics): BrushDynamics;
|
|
205
205
|
declare const BRUSH_ID: RegExp;
|
|
206
|
-
/**
|
|
207
|
-
|
|
206
|
+
/** Brush settings to change or read: any subset of a brush, its tip, dynamics and mixer. */
|
|
207
|
+
type PaintBrushInput = Partial<Omit<PaintBrush, 'tip' | 'dynamics' | 'mixer'>> & {
|
|
208
208
|
tip?: Partial<BrushSettings>;
|
|
209
209
|
dynamics?: Partial<BrushDynamics>;
|
|
210
210
|
mixer?: Partial<MixerSettings>;
|
|
211
|
-
}
|
|
211
|
+
};
|
|
212
|
+
/** A brush with every field in range; missing fields come from `base` (default: a plain round dab brush). */
|
|
213
|
+
declare function normalizePaintBrush(raw?: PaintBrushInput, base?: PaintBrush): PaintBrush;
|
|
212
214
|
/** The built-in brush library. */
|
|
213
215
|
declare const BUILTIN_BRUSHES: readonly PaintBrush[];
|
|
214
216
|
declare const DEFAULT_BRUSH_ID = "pencil-6b";
|
|
@@ -517,6 +519,8 @@ interface StrokeSessionInit {
|
|
|
517
519
|
/** The stroke's extra copies as affine maps (recorded with the stroke); `copies` holds all of them as engine copies. */
|
|
518
520
|
affineCopies: readonly Affine[];
|
|
519
521
|
copies: readonly StrokeCopy[];
|
|
522
|
+
/** Applied to each raw sample before it is painted and recorded (perspective snapping). */
|
|
523
|
+
inputFilter?: (p: PenPoint) => PenPoint;
|
|
520
524
|
/** Mixer engine: the brush load at the start of the stroke. */
|
|
521
525
|
mixerLoad: MixerLoad;
|
|
522
526
|
}
|
|
@@ -657,6 +661,9 @@ interface SerializeOptions {
|
|
|
657
661
|
strokes?: boolean;
|
|
658
662
|
/** Later-phase fields to write as they were read. */
|
|
659
663
|
extensions?: PaintDocumentExtensions;
|
|
664
|
+
/** Painting guides (symmetry, perspective, tracing and reference images as PNG data URLs). */
|
|
665
|
+
guides?: unknown;
|
|
666
|
+
swatches?: unknown;
|
|
660
667
|
}
|
|
661
668
|
/** The document as JSON with inline PNG data URLs. */
|
|
662
669
|
declare function serializePaintDocument(state: PaintDocumentState, options?: SerializeOptions): SerializedPaintDocument;
|
|
@@ -665,6 +672,9 @@ declare function serializePaintDocumentExternal(state: PaintDocumentState, store
|
|
|
665
672
|
interface LoadedPaintDocument {
|
|
666
673
|
state: PaintDocumentState;
|
|
667
674
|
extensions: PaintDocumentExtensions;
|
|
675
|
+
/** The saved guides and swatches, as stored (the controller validates them). */
|
|
676
|
+
guides?: unknown;
|
|
677
|
+
swatches?: unknown;
|
|
668
678
|
/** What could not be read (the rest still loads). */
|
|
669
679
|
problems: string[];
|
|
670
680
|
}
|
|
@@ -815,6 +825,17 @@ type ImageEncoder = (image: {
|
|
|
815
825
|
}, format: 'image/jpeg' | 'image/webp', quality: number) => Promise<Uint8Array>;
|
|
816
826
|
/** An encoder through `OffscreenCanvas`, or `null` where there is none (Node, tests). */
|
|
817
827
|
declare function defaultImageEncoder(): ImageEncoder | null;
|
|
828
|
+
/**
|
|
829
|
+
* Decodes an image file (PNG, JPEG, WebP, … whatever the browser reads) into RGBA pixels through
|
|
830
|
+
* `createImageBitmap` and an `OffscreenCanvas`. Browser and Worker only.
|
|
831
|
+
*/
|
|
832
|
+
declare function decodeImageBlob(blob: Blob): Promise<{
|
|
833
|
+
width: number;
|
|
834
|
+
height: number;
|
|
835
|
+
data: Uint8ClampedArray;
|
|
836
|
+
}>;
|
|
837
|
+
/** Saves bytes as a file through a temporary link. Browser only. */
|
|
838
|
+
declare function downloadBytes(bytes: Uint8Array | string, fileName: string, mimeType: string): void;
|
|
818
839
|
|
|
819
840
|
/**
|
|
820
841
|
* Brush thumbnails: a test stroke (an S-curve with pressure swelling and fading, at a steady
|
|
@@ -837,6 +858,213 @@ declare function renderBrushThumbnail(brush: PaintBrush, options: {
|
|
|
837
858
|
color: string;
|
|
838
859
|
}): BrushThumbnail;
|
|
839
860
|
|
|
861
|
+
/**
|
|
862
|
+
* Painting guides: mirror and kaleidoscope symmetry (every stroke paints its reflected or rotated
|
|
863
|
+
* copies as one stroke), perspective guides with one to three vanishing points that strokes snap
|
|
864
|
+
* to, a tracing image under the paint (optionally the source of the stroke colour), and floating
|
|
865
|
+
* reference images to pick colours from. Geometry only: no pixels, no DOM.
|
|
866
|
+
*/
|
|
867
|
+
|
|
868
|
+
type SymmetryMode = 'off' | 'vertical' | 'horizontal' | 'dual' | 'diagonal' | 'kaleidoscope';
|
|
869
|
+
declare const SYMMETRY_MODES: readonly SymmetryMode[];
|
|
870
|
+
interface SymmetryGuide {
|
|
871
|
+
mode: SymmetryMode;
|
|
872
|
+
/** Centre of the axes in document pixels (default the canvas centre). */
|
|
873
|
+
center: {
|
|
874
|
+
x: number;
|
|
875
|
+
y: number;
|
|
876
|
+
};
|
|
877
|
+
/** Turns the axes, degrees clockwise (default 0). */
|
|
878
|
+
rotation: number;
|
|
879
|
+
/** Kaleidoscope: number of segments, 2..32 (default 6). */
|
|
880
|
+
segments: number;
|
|
881
|
+
/** Kaleidoscope: reflect every other segment as well as rotating (default true), like a real kaleidoscope. */
|
|
882
|
+
mirror: boolean;
|
|
883
|
+
}
|
|
884
|
+
interface Point2 {
|
|
885
|
+
x: number;
|
|
886
|
+
y: number;
|
|
887
|
+
}
|
|
888
|
+
interface PerspectiveGuide {
|
|
889
|
+
enabled: boolean;
|
|
890
|
+
/** One to three vanishing points in document pixels (they may lie outside the canvas). */
|
|
891
|
+
points: Point2[];
|
|
892
|
+
/** Strokes snap to the guide lines (default true when enabled). */
|
|
893
|
+
snap: boolean;
|
|
894
|
+
}
|
|
895
|
+
/** A view-only image under the paint, placed over the canvas. */
|
|
896
|
+
interface TracingImage {
|
|
897
|
+
/** PNG or JPEG data URL. */
|
|
898
|
+
src: string;
|
|
899
|
+
/** Natural size of the image in pixels. */
|
|
900
|
+
width: number;
|
|
901
|
+
height: number;
|
|
902
|
+
/** Where it is drawn, in document pixels (default: fitted to the canvas). */
|
|
903
|
+
rect: {
|
|
904
|
+
x: number;
|
|
905
|
+
y: number;
|
|
906
|
+
width: number;
|
|
907
|
+
height: number;
|
|
908
|
+
};
|
|
909
|
+
/** 0..1 (default 0.35). */
|
|
910
|
+
opacity: number;
|
|
911
|
+
visible: boolean;
|
|
912
|
+
/** Strokes without an explicit colour take the tracing image's colour where they start. */
|
|
913
|
+
sampleColors: boolean;
|
|
914
|
+
}
|
|
915
|
+
/** A floating image to look at and pick colours from (shown beside the canvas, never painted). */
|
|
916
|
+
interface ReferenceImage {
|
|
917
|
+
id: string;
|
|
918
|
+
name: string;
|
|
919
|
+
src: string;
|
|
920
|
+
width: number;
|
|
921
|
+
height: number;
|
|
922
|
+
/** Where the panel floats over the viewport, in screen pixels, and its displayed width. */
|
|
923
|
+
x: number;
|
|
924
|
+
y: number;
|
|
925
|
+
displayWidth: number;
|
|
926
|
+
visible: boolean;
|
|
927
|
+
}
|
|
928
|
+
interface PaintGuides {
|
|
929
|
+
symmetry: SymmetryGuide;
|
|
930
|
+
perspective: PerspectiveGuide;
|
|
931
|
+
tracing: TracingImage | null;
|
|
932
|
+
references: ReferenceImage[];
|
|
933
|
+
}
|
|
934
|
+
declare function defaultGuides(canvas: {
|
|
935
|
+
width: number;
|
|
936
|
+
height: number;
|
|
937
|
+
}): PaintGuides;
|
|
938
|
+
declare const MAX_COORDINATE = 1000000;
|
|
939
|
+
declare function normalizeSymmetry(raw: Partial<SymmetryGuide> | Record<string, unknown>, base: SymmetryGuide): SymmetryGuide;
|
|
940
|
+
/** The axis directions of a mirror mode (radians), as photocraft's `directions`. */
|
|
941
|
+
declare function symmetryAxisAngles(g: SymmetryGuide): number[];
|
|
942
|
+
/**
|
|
943
|
+
* The extra copies a stroke paints under the symmetry guide, as affine maps (the stroke itself is
|
|
944
|
+
* not included). Vertical, horizontal and diagonal: one reflection. Dual: two reflections and the
|
|
945
|
+
* point reflection. Kaleidoscope: rotations by 360°/n, and with `mirror` the reflections between them.
|
|
946
|
+
*/
|
|
947
|
+
declare function symmetryCopies(g: SymmetryGuide): Affine[];
|
|
948
|
+
/** The axes clipped to the canvas, for drawing (photocraft's `segments`). */
|
|
949
|
+
declare function symmetryAxisSegments(g: SymmetryGuide, size: {
|
|
950
|
+
width: number;
|
|
951
|
+
height: number;
|
|
952
|
+
}): Array<[Point2, Point2]>;
|
|
953
|
+
declare function normalizePerspective(raw: Partial<PerspectiveGuide> | Record<string, unknown>, base: PerspectiveGuide): PerspectiveGuide;
|
|
954
|
+
/** The line families a perspective guide snaps to at `p`: unit directions. */
|
|
955
|
+
declare function perspectiveDirections(g: PerspectiveGuide, p: Point2): Point2[];
|
|
956
|
+
/** How far the pen must move before a stroke chooses its perspective line (document pixels). */
|
|
957
|
+
declare const SNAP_DECIDE_DISTANCE = 6;
|
|
958
|
+
/**
|
|
959
|
+
* Snaps one stroke to a perspective guide: once the pen has moved `SNAP_DECIDE_DISTANCE` from
|
|
960
|
+
* where it started, the stroke picks the guide line through its start that best matches its
|
|
961
|
+
* direction, and every sample after that is projected onto the line.
|
|
962
|
+
*/
|
|
963
|
+
declare class PerspectiveSnapper {
|
|
964
|
+
private readonly guide;
|
|
965
|
+
private start;
|
|
966
|
+
private dir;
|
|
967
|
+
constructor(guide: PerspectiveGuide);
|
|
968
|
+
/** The line the stroke follows, once chosen. */
|
|
969
|
+
get line(): {
|
|
970
|
+
from: Point2;
|
|
971
|
+
direction: Point2;
|
|
972
|
+
} | null;
|
|
973
|
+
snap<P extends Point2>(p: P): P;
|
|
974
|
+
}
|
|
975
|
+
/** Guide lines to draw for a perspective guide: rays from each vanishing point through the canvas. */
|
|
976
|
+
declare function perspectiveGuideLines(g: PerspectiveGuide, size: {
|
|
977
|
+
width: number;
|
|
978
|
+
height: number;
|
|
979
|
+
}, count?: number): Array<[Point2, Point2]>;
|
|
980
|
+
|
|
981
|
+
/**
|
|
982
|
+
* Colour for painters: hex / RGB / HSV / HSL conversions, a colour wheel that is either the
|
|
983
|
+
* painter's red-yellow-blue wheel (where red's complement is green) or the RGB wheel (where it is
|
|
984
|
+
* cyan), harmonies on it, and swatches.
|
|
985
|
+
*/
|
|
986
|
+
type Rgb255 = [number, number, number];
|
|
987
|
+
declare function parseHexColor(value: unknown, what?: string): Rgb255;
|
|
988
|
+
declare function rgbToHexColor(r: number, g: number, b: number): string;
|
|
989
|
+
/** RGB 0..255 → HSV with h in degrees 0..360, s and v 0..1. */
|
|
990
|
+
declare function rgbToHsv(r: number, g: number, b: number): {
|
|
991
|
+
h: number;
|
|
992
|
+
s: number;
|
|
993
|
+
v: number;
|
|
994
|
+
};
|
|
995
|
+
declare function hsvToRgb(h: number, s: number, v: number): Rgb255;
|
|
996
|
+
/** RGB 0..255 → HSL with h in degrees, s and l 0..1. */
|
|
997
|
+
declare function rgbToHsl(r: number, g: number, b: number): {
|
|
998
|
+
h: number;
|
|
999
|
+
s: number;
|
|
1000
|
+
l: number;
|
|
1001
|
+
};
|
|
1002
|
+
declare function hslToRgb(h: number, s: number, l: number): Rgb255;
|
|
1003
|
+
/** Which wheel hues live on: `ryb` (painter's: red ↔ green complements) or `rgb` (red ↔ cyan). */
|
|
1004
|
+
type ColorWheel = 'ryb' | 'rgb';
|
|
1005
|
+
/** A wheel angle (degrees) → an RGB hue. */
|
|
1006
|
+
declare function wheelToHue(angle: number, wheel: ColorWheel): number;
|
|
1007
|
+
/** An RGB hue → its wheel angle (degrees). */
|
|
1008
|
+
declare function hueToWheel(hue: number, wheel: ColorWheel): number;
|
|
1009
|
+
type HarmonyKind = 'complementary' | 'split-complementary' | 'analogous' | 'triadic' | 'tetradic' | 'square' | 'monochromatic';
|
|
1010
|
+
declare const HARMONY_KINDS: readonly HarmonyKind[];
|
|
1011
|
+
interface HarmonyColor {
|
|
1012
|
+
color: string;
|
|
1013
|
+
/** Position on the wheel, degrees. */
|
|
1014
|
+
angle: number;
|
|
1015
|
+
}
|
|
1016
|
+
/**
|
|
1017
|
+
* The colours of a harmony around `base`, the base first. Hue-based harmonies keep the base's
|
|
1018
|
+
* saturation and value and turn it around the wheel; `analogous` spreads by `spread` degrees
|
|
1019
|
+
* (default 30); `monochromatic` keeps the hue and steps the lightness.
|
|
1020
|
+
*/
|
|
1021
|
+
declare function colorHarmony(base: string, kind: HarmonyKind, options?: {
|
|
1022
|
+
wheel?: ColorWheel;
|
|
1023
|
+
spread?: number;
|
|
1024
|
+
}): HarmonyColor[];
|
|
1025
|
+
interface Swatch {
|
|
1026
|
+
color: string;
|
|
1027
|
+
name?: string;
|
|
1028
|
+
}
|
|
1029
|
+
/** A starting palette of our own generic paint colours. */
|
|
1030
|
+
declare const DEFAULT_SWATCHES: readonly Swatch[];
|
|
1031
|
+
|
|
1032
|
+
/**
|
|
1033
|
+
* The mixing pad: a small canvas beside the painting to put paint on, smear it with a palette
|
|
1034
|
+
* knife and pick the mixed colour from. Paint is laid with the Mixer Brush in pigment mode and the
|
|
1035
|
+
* knife is a pigment smudge, so blue and yellow pushed together make green. It is scratch space:
|
|
1036
|
+
* not part of the painting and not in its undo history.
|
|
1037
|
+
*/
|
|
1038
|
+
|
|
1039
|
+
type MixingPadTool = 'paint' | 'knife';
|
|
1040
|
+
declare const MIXING_PAD_WIDTH = 360;
|
|
1041
|
+
declare const MIXING_PAD_HEIGHT = 220;
|
|
1042
|
+
declare class MixingPad {
|
|
1043
|
+
readonly width = 360;
|
|
1044
|
+
readonly height = 220;
|
|
1045
|
+
private surface;
|
|
1046
|
+
/** Increments on every change (for redrawing). */
|
|
1047
|
+
version: number;
|
|
1048
|
+
/** Paints (`paint`, with `color`) or smears (`knife`) through `points` in pad pixels. */
|
|
1049
|
+
stroke(points: readonly PenPoint[], options: {
|
|
1050
|
+
tool: MixingPadTool;
|
|
1051
|
+
color: string;
|
|
1052
|
+
size?: number;
|
|
1053
|
+
}): {
|
|
1054
|
+
bounds: {
|
|
1055
|
+
x: number;
|
|
1056
|
+
y: number;
|
|
1057
|
+
width: number;
|
|
1058
|
+
height: number;
|
|
1059
|
+
} | null;
|
|
1060
|
+
};
|
|
1061
|
+
/** The average colour within `radius` pixels of (x, y), or `null` where the pad is bare. */
|
|
1062
|
+
pick(x: number, y: number, radius?: number): string | null;
|
|
1063
|
+
clear(): void;
|
|
1064
|
+
/** The pad over white, `width × height` RGBA. */
|
|
1065
|
+
pixels(): Uint8ClampedArray;
|
|
1066
|
+
}
|
|
1067
|
+
|
|
840
1068
|
/**
|
|
841
1069
|
* `PaintEditorController`: the natural-media paint editor's state, framework-free.
|
|
842
1070
|
*
|
|
@@ -887,6 +1115,12 @@ interface PaintEditorState {
|
|
|
887
1115
|
canRedo: boolean;
|
|
888
1116
|
undoLabel: string | null;
|
|
889
1117
|
redoLabel: string | null;
|
|
1118
|
+
/** Mirror / kaleidoscope, perspective, tracing image and reference images (saved with the document, not undo steps). */
|
|
1119
|
+
guides: PaintGuides;
|
|
1120
|
+
/** The colour swatches (saved with the document, not undo steps). */
|
|
1121
|
+
swatches: readonly Swatch[];
|
|
1122
|
+
/** Changes whenever the mixing pad does. */
|
|
1123
|
+
mixingPadVersion: number;
|
|
890
1124
|
/** A stroke is in progress. */
|
|
891
1125
|
stroking: boolean;
|
|
892
1126
|
/** Increments on every change. */
|
|
@@ -916,11 +1150,18 @@ interface PaintStrokeInit {
|
|
|
916
1150
|
/** Default the active brush. */
|
|
917
1151
|
brushId?: string;
|
|
918
1152
|
/** Changes to the brush for this stroke only. */
|
|
919
|
-
brush?:
|
|
1153
|
+
brush?: PaintBrushInput;
|
|
920
1154
|
/** Jitter seed (default: a new one per stroke). */
|
|
921
1155
|
seed?: number;
|
|
922
|
-
/** Extra copies of the stroke as affine maps (
|
|
1156
|
+
/** Extra copies of the stroke as affine maps (default: the symmetry guide's). */
|
|
923
1157
|
copies?: readonly Affine[];
|
|
1158
|
+
/** Snap the samples to the perspective guide (default true for `beginStroke`, false for `paintStroke`). */
|
|
1159
|
+
snapToPerspective?: boolean;
|
|
1160
|
+
/** Where the stroke starts, for taking its colour from the tracing image before the first sample (`beginStroke`). */
|
|
1161
|
+
start?: {
|
|
1162
|
+
x: number;
|
|
1163
|
+
y: number;
|
|
1164
|
+
};
|
|
924
1165
|
}
|
|
925
1166
|
interface LayerUpdate {
|
|
926
1167
|
name?: string;
|
|
@@ -988,6 +1229,13 @@ declare class PaintEditorController {
|
|
|
988
1229
|
private dirty;
|
|
989
1230
|
private seedCounter;
|
|
990
1231
|
private strokeCounter;
|
|
1232
|
+
private guides;
|
|
1233
|
+
private swatches;
|
|
1234
|
+
private readonly pad;
|
|
1235
|
+
private tracingVersion;
|
|
1236
|
+
private tracingCache;
|
|
1237
|
+
private readonly imagePixels;
|
|
1238
|
+
private nextReferenceId;
|
|
991
1239
|
private readonly viewCompositor;
|
|
992
1240
|
private readonly exportCompositor;
|
|
993
1241
|
constructor(options?: PaintEditorOptions);
|
|
@@ -1072,12 +1320,12 @@ declare class PaintEditorController {
|
|
|
1072
1320
|
*/
|
|
1073
1321
|
setBrush(update?: {
|
|
1074
1322
|
id?: string;
|
|
1075
|
-
} & Omit<
|
|
1323
|
+
} & Omit<PaintBrushInput, 'id'>): PaintBrush;
|
|
1076
1324
|
/** Saves the active brush (or `brush`) into the user library under `id` / `name`. */
|
|
1077
1325
|
saveBrush(options: {
|
|
1078
1326
|
id: string;
|
|
1079
1327
|
name?: string;
|
|
1080
|
-
brush?:
|
|
1328
|
+
brush?: PaintBrushInput;
|
|
1081
1329
|
}): PaintBrush;
|
|
1082
1330
|
removeBrush(id: string): void;
|
|
1083
1331
|
/** The user's saved brushes. */
|
|
@@ -1154,6 +1402,8 @@ declare class PaintEditorController {
|
|
|
1154
1402
|
private currentLayers;
|
|
1155
1403
|
/** View-only layers between the paper and the paint (the painting guides add the tracing image). */
|
|
1156
1404
|
protected underlayLayers(): ViewLayer[];
|
|
1405
|
+
/** The tracing image resampled onto the canvas (cached until it or the canvas changes). */
|
|
1406
|
+
private tracingNode;
|
|
1157
1407
|
private renderLayers;
|
|
1158
1408
|
/**
|
|
1159
1409
|
* Composites the viewport stack (paper, view-only underlays, layers with the live stroke) tile by
|
|
@@ -1210,10 +1460,79 @@ declare class PaintEditorController {
|
|
|
1210
1460
|
width: number;
|
|
1211
1461
|
height: number;
|
|
1212
1462
|
};
|
|
1463
|
+
private setGuides;
|
|
1464
|
+
/** Mirror and kaleidoscope painting: every new stroke paints its copies too (one stroke, one undo step). */
|
|
1465
|
+
setSymmetry(update: Partial<SymmetryGuide>): SymmetryGuide;
|
|
1466
|
+
/** Perspective guides with one to three vanishing points that pointer strokes snap to. */
|
|
1467
|
+
setPerspective(update: Partial<PerspectiveGuide>): PerspectiveGuide;
|
|
1468
|
+
/** An image from a PNG (base64 or data URL) or from RGBA pixels, stored as a PNG data URL. */
|
|
1469
|
+
private importImage;
|
|
1470
|
+
private decodeImage;
|
|
1471
|
+
/**
|
|
1472
|
+
* Puts an image under the paint to trace over: view only, never in exports. Placed to fit the
|
|
1473
|
+
* canvas unless `rect` is given; `sampleColors` makes strokes take their colour from it.
|
|
1474
|
+
*/
|
|
1475
|
+
setTracingImage(options: {
|
|
1476
|
+
png?: string;
|
|
1477
|
+
pixels?: PixelImage;
|
|
1478
|
+
rect?: TracingImage['rect'];
|
|
1479
|
+
opacity?: number;
|
|
1480
|
+
sampleColors?: boolean;
|
|
1481
|
+
}): TracingImage;
|
|
1482
|
+
/** Changes the tracing image's opacity, visibility, placement or colour sampling. */
|
|
1483
|
+
updateTracing(update: Partial<Pick<TracingImage, 'opacity' | 'visible' | 'sampleColors' | 'rect'>>, base?: TracingImage | null): TracingImage;
|
|
1484
|
+
clearTracingImage(): void;
|
|
1485
|
+
/** The tracing image's colour at a document pixel, or `null` outside it or where it is clear. */
|
|
1486
|
+
sampleTracingColor(x: number, y: number): string | null;
|
|
1487
|
+
/** Adds a floating reference image to look at and pick colours from. */
|
|
1488
|
+
addReferenceImage(options: {
|
|
1489
|
+
png?: string;
|
|
1490
|
+
pixels?: PixelImage;
|
|
1491
|
+
name?: string;
|
|
1492
|
+
x?: number;
|
|
1493
|
+
y?: number;
|
|
1494
|
+
displayWidth?: number;
|
|
1495
|
+
}): ReferenceImage;
|
|
1496
|
+
private requireReference;
|
|
1497
|
+
/** Moves, resizes, renames, shows or hides a reference image. */
|
|
1498
|
+
updateReferenceImage(id: string, update: Partial<Pick<ReferenceImage, 'name' | 'x' | 'y' | 'displayWidth' | 'visible'>>): ReferenceImage;
|
|
1499
|
+
removeReferenceImage(id: string): void;
|
|
1500
|
+
/** A reference image's pixels (decoded once). */
|
|
1501
|
+
referencePixels(id: string): PixelImage;
|
|
1502
|
+
/** The colour of a reference image at its pixel (x, y). */
|
|
1503
|
+
pickReferenceColor(id: string, x: number, y: number): string;
|
|
1504
|
+
private readGuides;
|
|
1505
|
+
/** Colour harmonies around a colour (default the paint colour) on the painter's RYB wheel or the RGB wheel. */
|
|
1506
|
+
harmony(kind: HarmonyKind, options?: {
|
|
1507
|
+
color?: string;
|
|
1508
|
+
wheel?: ColorWheel;
|
|
1509
|
+
spread?: number;
|
|
1510
|
+
}): HarmonyColor[];
|
|
1511
|
+
addSwatch(color: string, name?: string): Swatch[];
|
|
1512
|
+
removeSwatch(index: number): Swatch[];
|
|
1513
|
+
setSwatches(swatches: readonly Swatch[]): Swatch[];
|
|
1514
|
+
get mixingPad(): MixingPad;
|
|
1515
|
+
/** Paints (`paint`) or smears with the palette knife (`knife`) on the mixing pad, in pad pixels. */
|
|
1516
|
+
mixingPadStroke(points: readonly PenPoint[], options?: {
|
|
1517
|
+
tool?: MixingPadTool;
|
|
1518
|
+
color?: string;
|
|
1519
|
+
size?: number;
|
|
1520
|
+
}): {
|
|
1521
|
+
bounds: RasterRect | null;
|
|
1522
|
+
};
|
|
1523
|
+
/** Picks the mixed colour on the pad (averaged over `radius` px); with `setColor` it becomes the paint colour. */
|
|
1524
|
+
mixingPadPick(x: number, y: number, options?: {
|
|
1525
|
+
radius?: number;
|
|
1526
|
+
setColor?: boolean;
|
|
1527
|
+
}): string | null;
|
|
1528
|
+
clearMixingPad(): void;
|
|
1213
1529
|
/** A layer's tile surface (live while stroking), for thumbnails. */
|
|
1214
1530
|
layerSurface(id: string): TiledSurface | null;
|
|
1215
1531
|
}
|
|
1216
1532
|
|
|
1533
|
+
/** Largest tracing or reference image side, in pixels. */
|
|
1534
|
+
declare const MAX_IMAGE_SIDE = 8192;
|
|
1535
|
+
|
|
1217
1536
|
/**
|
|
1218
1537
|
* Agent tools for the paint editor (`createPaintEditorToolProvider`). Strict schemas, every
|
|
1219
1538
|
* argument described, all four annotations. Each write is one undo step (or editor state, said so)
|
|
@@ -1230,4 +1549,132 @@ interface PaintEditorToolProviderOptions {
|
|
|
1230
1549
|
/** Agent tools for one paint editor. */
|
|
1231
1550
|
declare function createPaintEditorToolProvider(controller: PaintEditorController, options?: PaintEditorToolProviderOptions): AgentToolProvider;
|
|
1232
1551
|
|
|
1233
|
-
|
|
1552
|
+
/**
|
|
1553
|
+
* Framework-free UI logic shared by the React and Svelte paint editors, so both behave the same:
|
|
1554
|
+
*
|
|
1555
|
+
* - `PaintGesture` turns pointer events (structurally typed, no DOM import) into strokes (with
|
|
1556
|
+
* coalesced samples and a predicted tail), colour picks, pans, view rotation and zoom, with palm
|
|
1557
|
+
* rejection while a pen is down.
|
|
1558
|
+
* - `PaintCanvasPresenter` keeps a document-sized 2D canvas up to date from the compositor,
|
|
1559
|
+
* uploading only the tiles that changed.
|
|
1560
|
+
* - Guide overlays as line segments, and the slider tables of the brush and paper panels.
|
|
1561
|
+
*/
|
|
1562
|
+
|
|
1563
|
+
/** The Pointer Event fields the gesture reads. */
|
|
1564
|
+
interface PaintPointerEvent extends PointerSample {
|
|
1565
|
+
pointerId: number;
|
|
1566
|
+
clientX: number;
|
|
1567
|
+
clientY: number;
|
|
1568
|
+
button?: number;
|
|
1569
|
+
buttons?: number;
|
|
1570
|
+
shiftKey?: boolean;
|
|
1571
|
+
altKey?: boolean;
|
|
1572
|
+
ctrlKey?: boolean;
|
|
1573
|
+
metaKey?: boolean;
|
|
1574
|
+
getCoalescedEvents?(): PaintPointerEvent[];
|
|
1575
|
+
getPredictedEvents?(): PaintPointerEvent[];
|
|
1576
|
+
}
|
|
1577
|
+
type PaintTool = 'brush' | 'eyedropper' | 'pan' | 'rotate';
|
|
1578
|
+
declare const PAINT_TOOLS: ReadonlyArray<{
|
|
1579
|
+
id: PaintTool;
|
|
1580
|
+
label: string;
|
|
1581
|
+
key: string;
|
|
1582
|
+
}>;
|
|
1583
|
+
/** Where the viewport element is on screen and how big it is (CSS pixels). */
|
|
1584
|
+
interface ViewportBox {
|
|
1585
|
+
left: number;
|
|
1586
|
+
top: number;
|
|
1587
|
+
width: number;
|
|
1588
|
+
height: number;
|
|
1589
|
+
}
|
|
1590
|
+
declare class PaintGesture {
|
|
1591
|
+
private readonly controller;
|
|
1592
|
+
private readonly box;
|
|
1593
|
+
tool: PaintTool;
|
|
1594
|
+
/** The last refusal (a hidden or locked layer), for the editor to show. */
|
|
1595
|
+
error: string | null;
|
|
1596
|
+
/** The predicted tail of the current stroke in document pixels (draw it as a thin preview). */
|
|
1597
|
+
predicted: PenPoint[];
|
|
1598
|
+
private mode;
|
|
1599
|
+
private penAt;
|
|
1600
|
+
private penDown;
|
|
1601
|
+
constructor(controller: PaintEditorController, box: () => ViewportBox);
|
|
1602
|
+
private doc;
|
|
1603
|
+
private pen;
|
|
1604
|
+
/** Pointer down; returns true when the gesture took the pointer (capture it). */
|
|
1605
|
+
down(e: PaintPointerEvent): boolean;
|
|
1606
|
+
private pick;
|
|
1607
|
+
move(e: PaintPointerEvent): void;
|
|
1608
|
+
up(e: PaintPointerEvent): void;
|
|
1609
|
+
cancel(): void;
|
|
1610
|
+
get active(): boolean;
|
|
1611
|
+
/** Wheel: zoom about the pointer (Ctrl / pinch or plain wheel), Shift+wheel rotates the view. */
|
|
1612
|
+
wheel(e: {
|
|
1613
|
+
clientX: number;
|
|
1614
|
+
clientY: number;
|
|
1615
|
+
deltaY: number;
|
|
1616
|
+
shiftKey?: boolean;
|
|
1617
|
+
}): void;
|
|
1618
|
+
}
|
|
1619
|
+
/** Keyboard shortcuts shared by both editors; returns true when it handled the key. */
|
|
1620
|
+
declare function handlePaintShortcut(controller: PaintEditorController, gesture: PaintGesture, e: {
|
|
1621
|
+
key: string;
|
|
1622
|
+
ctrlKey?: boolean;
|
|
1623
|
+
metaKey?: boolean;
|
|
1624
|
+
shiftKey?: boolean;
|
|
1625
|
+
target?: unknown;
|
|
1626
|
+
}): boolean;
|
|
1627
|
+
/** The 2D context methods the presenter uses (a `CanvasRenderingContext2D`). */
|
|
1628
|
+
interface Paint2DContext {
|
|
1629
|
+
createImageData(width: number, height: number): {
|
|
1630
|
+
data: Uint8ClampedArray;
|
|
1631
|
+
};
|
|
1632
|
+
putImageData(image: never, dx: number, dy: number, sx?: number, sy?: number, sw?: number, sh?: number): void;
|
|
1633
|
+
}
|
|
1634
|
+
/** Keeps a document-sized canvas in step with the controller, tile by tile. */
|
|
1635
|
+
declare class PaintCanvasPresenter {
|
|
1636
|
+
private readonly controller;
|
|
1637
|
+
private readonly uploaded;
|
|
1638
|
+
private scratch;
|
|
1639
|
+
private size;
|
|
1640
|
+
constructor(controller: PaintEditorController);
|
|
1641
|
+
/** Draws what changed into `ctx` (a canvas the size of the document); returns the tiles drawn. */
|
|
1642
|
+
render(ctx: Paint2DContext): number;
|
|
1643
|
+
}
|
|
1644
|
+
/** Lines to draw over the canvas for the guides, in document pixels, with a style key. */
|
|
1645
|
+
declare function guideOverlay(controller: PaintEditorController): Array<{
|
|
1646
|
+
from: Point2;
|
|
1647
|
+
to: Point2;
|
|
1648
|
+
kind: 'symmetry' | 'perspective' | 'snap';
|
|
1649
|
+
}>;
|
|
1650
|
+
/** One slider of a panel: a path into the brush (or paper) settings. */
|
|
1651
|
+
interface SliderControl {
|
|
1652
|
+
path: string;
|
|
1653
|
+
label: string;
|
|
1654
|
+
min: number;
|
|
1655
|
+
max: number;
|
|
1656
|
+
step: number;
|
|
1657
|
+
}
|
|
1658
|
+
declare const BRUSH_SLIDERS: readonly SliderControl[];
|
|
1659
|
+
declare const PAPER_SLIDERS: readonly SliderControl[];
|
|
1660
|
+
/** Reads `a.b` from an object. */
|
|
1661
|
+
declare function readPath(obj: unknown, path: string): number;
|
|
1662
|
+
/** `{a: {b: value}}` for `a.b`, keeping the rest of `obj`'s `a`. */
|
|
1663
|
+
declare function patchPath(obj: Record<string, unknown>, path: string, value: number): Record<string, unknown>;
|
|
1664
|
+
/** The point on a colour wheel of `radius` (centre 0, 0) for a wheel angle in degrees, red at the top. */
|
|
1665
|
+
declare function wheelPoint(angle: number, radius: number): Point2;
|
|
1666
|
+
/** The wheel angle (degrees, red at the top, clockwise) of a point relative to the wheel centre. */
|
|
1667
|
+
declare function wheelAngle(x: number, y: number): number;
|
|
1668
|
+
/**
|
|
1669
|
+
* A hue ring for a colour wheel, `size × size` RGBA: hues at full saturation and value between
|
|
1670
|
+
* `inner` and 1 of the radius, red at the top, laid out on the RYB or RGB wheel.
|
|
1671
|
+
*/
|
|
1672
|
+
declare function renderColorWheel(size: number, wheel: ColorWheel, inner?: number): {
|
|
1673
|
+
width: number;
|
|
1674
|
+
height: number;
|
|
1675
|
+
data: Uint8ClampedArray;
|
|
1676
|
+
};
|
|
1677
|
+
/** The colour for a click on the wheel ring at (dx, dy) from its centre, keeping `color`'s saturation and value. */
|
|
1678
|
+
declare function wheelPick(dx: number, dy: number, wheel: ColorWheel, color: string): string;
|
|
1679
|
+
|
|
1680
|
+
export { type Affine, BRUSH_ID, BRUSH_ROTATIONS, BRUSH_SLIDERS, BUILTIN_BRUSHES, BlendMode, type BrushDynamics, type BrushLibraryFile, type BrushRotation, type BrushThumbnail, type ColorWheel, DEFAULT_BRUSH_ID, DEFAULT_DPI, DEFAULT_DYNAMICS, DEFAULT_PAPER, DEFAULT_SWATCHES, DEFAULT_VIEW, DryStroke, type DryStrokeOptions, type FillLayerOptions, GRAIN_PATTERNS, GRAIN_TILE, type GrainPattern, type GrainTuning, HARMONY_KINDS, type Hand, type HarmonyColor, type HarmonyKind, IDENTITY_AFFINE, IDENTITY_COPY, type ImageEncoder, type ImageFormat, type ImageNode, type LayerUpdate, type Linear2, type LoadedPaintDocument, MAX_CANVAS_SIDE, MAX_COORDINATE, MAX_IMAGE_SIDE, MAX_ZOOM, MIN_CANVAS_SIDE, MIN_ZOOM, MIXING_PAD_HEIGHT, MIXING_PAD_WIDTH, MixingPad, type MixingPadTool, PAINT_BRUSH_CATEGORIES, PAINT_BRUSH_ENGINES, PAINT_FORMAT, PAINT_SCHEMA_VERSION, PAINT_TOOLS, PAPER_FAMILIES, PAPER_LIBRARY, PAPER_NODE_ID, PAPER_SLIDERS, type Paint2DContext, type PaintAssetStore, type PaintBrush, type PaintBrushCategory, type PaintBrushEngine, type PaintBrushInput, type PaintCanvas, PaintCanvasPresenter, PaintDocumentError, type PaintDocumentExtensions, type PaintDocumentState, PaintEditorController, PaintEditorError, type PaintEditorOptions, type PaintEditorState, type PaintEditorToolProviderOptions, PaintGesture, type PaintGroupLayer, type PaintGuides, type PaintLayer, type PaintLayerInfo, type PaintPixelLayer, type PaintPointerEvent, type PaintStrokeInit, type PaintStrokeResult, PaintStrokeSession, type PaintTool, type PaintView, type PaperFamily, PaperGrain, type PaperNode, type PaperSettings, type PaperTiling, type PenDab, PenDabWalker, type PenPoint, PenSmoother, type PerspectiveGuide, PerspectiveSnapper, type PixelImage, type Point2, type PointerSample, type RecordedStroke, type ReferenceImage, type RenderOptions, type ReplayOptions, type Rgb255, SNAP_DECIDE_DISTANCE, SYMMETRY_MODES, type SerializeOptions, type SerializedPaintDocument, type SliderControl, type StrokeCopy, type StrokeSessionHost, type StrokeSessionInit, type StrokeVariation, type Swatch, type SymmetryGuide, type SymmetryMode, TRACING_NODE_ID, TileableNoise, type TracingImage, type ViewLayer, type ViewportBox, affineCopy, applyAffine, brushToJSON, clonePaper, colorHarmony, composeAffine, createPaintCompositor, createPaintDocument, createPaintEditorToolProvider, createPaintLayer, decodeImageBlob, defaultGuides, defaultImageEncoder, deserializePaintDocument, deserializePaintDocumentAsync, documentExtensions, documentToScreen, downloadBytes, downsampleRgba, fitZoom, grainCatch, grainHeights, guideOverlay, handlePaintShortcut, hash2, hexToRgb8, hslToRgb, hsvToRgb, hueToWheel, invertAffine, isPalmTouch, mapPenPoint, mix32, mixerLoadForStroke, mixerTip, newPaintLayerId, normalizeBrushStroke, normalizeCanvas, normalizeDynamics, normalizePaintBrush, normalizePaper, normalizePerspective, normalizeRotation, normalizeSymmetry, normalizeView, paperGrain, paperKey, paperNode, paperPreset, parseBrushLibrary, parseHexColor, patchPath, penOrientation, perspectiveDirections, perspectiveGuideLines, pointerToPenPoint, rand01, randSigned, readPath, renderBrushThumbnail, renderColorWheel, renderPaper, rgbToHexColor, rgbToHsl, rgbToHsv, samplePressure, screenToDocument, seedFromString, serializePaintDocument, serializePaintDocumentExternal, strokeBounds, symmetryAxisAngles, symmetryAxisSegments, symmetryCopies, thumbnailStroke, tiltToOrientation, toStrokePoint, variationAffine, varyStroke, viewCssTransform, viewMatrix, viewPenToDocument, wheelAngle, wheelPick, wheelPoint, wheelToHue };
|