@pixerate/editor 0.266.2 → 0.268.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (149) hide show
  1. package/dist/agent/index.cjs +2 -2
  2. package/dist/agent/index.js +1 -1
  3. package/dist/animation-editor/controller.d.cts +8 -0
  4. package/dist/animation-editor/controller.d.ts +8 -0
  5. package/dist/animation-editor/effect-tools.d.cts +1 -1
  6. package/dist/animation-editor/effect-tools.d.ts +1 -1
  7. package/dist/animation-editor/index.cjs +175 -108
  8. package/dist/animation-editor/index.js +94 -27
  9. package/dist/brushes/index.cjs +201 -75
  10. package/dist/brushes/index.d.cts +4 -3
  11. package/dist/brushes/index.d.ts +4 -3
  12. package/dist/brushes/index.js +138 -12
  13. package/dist/brushes/library.d.cts +27 -1
  14. package/dist/brushes/library.d.ts +27 -1
  15. package/dist/brushes/profiles.d.cts +10 -1
  16. package/dist/brushes/profiles.d.ts +10 -1
  17. package/dist/brushes/schema.d.cts +4 -0
  18. package/dist/brushes/schema.d.ts +4 -0
  19. package/dist/brushes/sources.d.cts +114 -0
  20. package/dist/brushes/sources.d.ts +114 -0
  21. package/dist/brushes/types.d.cts +37 -5
  22. package/dist/brushes/types.d.ts +37 -5
  23. package/dist/brushes/ui.d.cts +40 -4
  24. package/dist/brushes/ui.d.ts +40 -4
  25. package/dist/{brushstrokeRender-KD453OBX.js → brushstrokeRender-A727TTNQ.js} +7 -7
  26. package/dist/{brushstrokeRender-FSUWXUZY.cjs → brushstrokeRender-WR2N5HHY.cjs} +23 -23
  27. package/dist/canvas/brushTypes.d.cts +12 -0
  28. package/dist/canvas/brushTypes.d.ts +12 -0
  29. package/dist/canvas/brushstroke.d.cts +1 -1
  30. package/dist/canvas/brushstroke.d.ts +1 -1
  31. package/dist/canvas/drawController.d.cts +19 -4
  32. package/dist/canvas/drawController.d.ts +19 -4
  33. package/dist/canvas/index.cjs +144 -105
  34. package/dist/canvas/index.js +46 -7
  35. package/dist/{chunk-TOID45I2.cjs → chunk-2WOGXEDX.cjs} +1 -1
  36. package/dist/{chunk-XORJ7UZO.cjs → chunk-3VHH6V67.cjs} +13 -12
  37. package/dist/{chunk-3C33YTNN.js → chunk-3XDSNIGF.js} +73 -6
  38. package/dist/chunk-62MFUHSI.cjs +802 -0
  39. package/dist/{chunk-R44Y3EFS.js → chunk-74ODPZLX.js} +17 -345
  40. package/dist/{chunk-GCVFEPJG.js → chunk-ACTHSQOI.js} +182 -0
  41. package/dist/chunk-ADMRNWR7.js +340 -0
  42. package/dist/{chunk-MVUQSK5J.cjs → chunk-B3G7BKUV.cjs} +111 -439
  43. package/dist/{chunk-DXYHQ2VN.js → chunk-BAZMCFVL.js} +1 -1
  44. package/dist/{chunk-VRK322ZC.cjs → chunk-BPJSI4NT.cjs} +2 -2
  45. package/dist/{chunk-RFJZGTHA.cjs → chunk-EU2ZZA6L.cjs} +400 -69
  46. package/dist/{chunk-XC6DPRYI.js → chunk-GSTSZPSR.js} +154 -949
  47. package/dist/{chunk-EZOJBP4D.js → chunk-HFY5LG5J.js} +1 -1
  48. package/dist/chunk-HVO6XCI4.js +802 -0
  49. package/dist/{chunk-YHDHFJUC.cjs → chunk-J5VQYK7T.cjs} +217 -1012
  50. package/dist/{chunk-XRXFVRGY.cjs → chunk-JBB3GDBB.cjs} +2483 -208
  51. package/dist/{chunk-ACFSFUQH.js → chunk-JL6YH5WD.js} +4 -0
  52. package/dist/{chunk-CIJBSUM5.js → chunk-KZI3YWKW.js} +353 -22
  53. package/dist/{chunk-4ODRXQRW.js → chunk-LETF75CA.js} +1 -1
  54. package/dist/{chunk-FQPUF2W2.cjs → chunk-NIBFKXMD.cjs} +217 -35
  55. package/dist/{chunk-AQZQWXEU.cjs → chunk-NPWWSCWT.cjs} +35 -35
  56. package/dist/{chunk-DOZ6F2K2.js → chunk-NSETJI74.js} +3 -2
  57. package/dist/{chunk-PE6YJMQT.cjs → chunk-PFHJS4HE.cjs} +20 -19
  58. package/dist/{chunk-7KNW3WXZ.cjs → chunk-QEVLRLUN.cjs} +63 -0
  59. package/dist/{chunk-LK4SXL3V.js → chunk-QNY7BDFP.js} +1 -1
  60. package/dist/{chunk-OTN6VB5S.cjs → chunk-RDFHWAHL.cjs} +5 -1
  61. package/dist/{chunk-PXDIAYB6.cjs → chunk-STLTOISW.cjs} +34 -214
  62. package/dist/{chunk-T2LDTEXK.js → chunk-UVTO3D4E.js} +2333 -58
  63. package/dist/{chunk-6JL2D5SG.js → chunk-VE6UKYQ2.js} +3 -2
  64. package/dist/{chunk-TXFWZ5ZJ.js → chunk-W6JDUXP3.js} +4 -184
  65. package/dist/{chunk-3SBLVGOM.cjs → chunk-YOVXQHA3.cjs} +23 -23
  66. package/dist/{chunk-WLUVZKVD.cjs → chunk-YXP6X3SY.cjs} +103 -36
  67. package/dist/chunk-YZWM6ZIP.cjs +340 -0
  68. package/dist/{chunk-472INMWH.js → chunk-ZA7L5YJB.js} +63 -0
  69. package/dist/commands/builtins.d.cts +12 -1
  70. package/dist/commands/builtins.d.ts +12 -1
  71. package/dist/commands/index.cjs +2 -2
  72. package/dist/commands/index.js +1 -1
  73. package/dist/image-editor/controller.d.cts +1 -1
  74. package/dist/image-editor/controller.d.ts +1 -1
  75. package/dist/image-editor/index.cjs +868 -864
  76. package/dist/image-editor/index.js +123 -119
  77. package/dist/paint/index.cjs +8 -6
  78. package/dist/paint/index.js +56 -54
  79. package/dist/paint-editor/brush-library-tools.d.cts +12 -2
  80. package/dist/paint-editor/brush-library-tools.d.ts +12 -2
  81. package/dist/paint-editor/brush-model.d.cts +29 -1
  82. package/dist/paint-editor/brush-model.d.ts +29 -1
  83. package/dist/paint-editor/brush-source-art.d.cts +32 -0
  84. package/dist/paint-editor/brush-source-art.d.ts +32 -0
  85. package/dist/paint-editor/controller.d.cts +11 -4
  86. package/dist/paint-editor/controller.d.ts +11 -4
  87. package/dist/paint-editor/dab-stroke.d.cts +2 -0
  88. package/dist/paint-editor/dab-stroke.d.ts +2 -0
  89. package/dist/paint-editor/engine.d.cts +11 -2
  90. package/dist/paint-editor/engine.d.ts +11 -2
  91. package/dist/paint-editor/index.cjs +967 -2335
  92. package/dist/paint-editor/index.d.cts +3 -1
  93. package/dist/paint-editor/index.d.ts +3 -1
  94. package/dist/paint-editor/index.js +394 -1762
  95. package/dist/paint-editor/path-samples.d.cts +2 -0
  96. package/dist/paint-editor/path-samples.d.ts +2 -0
  97. package/dist/paint-editor/presence.d.cts +20 -1
  98. package/dist/paint-editor/presence.d.ts +20 -1
  99. package/dist/paint-editor/stamp-tip.d.cts +8 -5
  100. package/dist/paint-editor/stamp-tip.d.ts +8 -5
  101. package/dist/paint-editor/thumbnails.d.cts +6 -0
  102. package/dist/paint-editor/thumbnails.d.ts +6 -0
  103. package/dist/paint-editor/tip-grain.d.cts +34 -0
  104. package/dist/paint-editor/tip-grain.d.ts +34 -0
  105. package/dist/raster/index.cjs +2 -2
  106. package/dist/raster/index.js +9 -9
  107. package/dist/stickers/helpers.d.cts +2 -0
  108. package/dist/stickers/helpers.d.ts +2 -0
  109. package/dist/stickers/index.cjs +41 -35
  110. package/dist/stickers/index.js +22 -16
  111. package/dist/stickers/types.d.cts +4 -2
  112. package/dist/stickers/types.d.ts +4 -2
  113. package/dist/vector/backdrop.d.cts +13 -0
  114. package/dist/vector/backdrop.d.ts +13 -0
  115. package/dist/vector/brushstroke.d.cts +54 -7
  116. package/dist/vector/brushstroke.d.ts +54 -7
  117. package/dist/vector/brushstrokeMedia.d.cts +96 -0
  118. package/dist/vector/brushstrokeMedia.d.ts +96 -0
  119. package/dist/vector/controller.d.cts +17 -3
  120. package/dist/vector/controller.d.ts +17 -3
  121. package/dist/vector/index.cjs +1850 -1390
  122. package/dist/vector/index.d.cts +2 -0
  123. package/dist/vector/index.d.ts +2 -0
  124. package/dist/vector/index.js +520 -60
  125. package/dist/vector/render.d.cts +6 -0
  126. package/dist/vector/render.d.ts +6 -0
  127. package/dist/vector/types.d.cts +14 -0
  128. package/dist/vector/types.d.ts +14 -0
  129. package/package.json +1 -1
  130. package/skills/pixerate-animation-editor/SKILL.md +1 -0
  131. package/skills/pixerate-brushes/SKILL.md +37 -10
  132. package/skills/pixerate-brushes-design/SKILL.md +15 -5
  133. package/skills/pixerate-brushes-design/evals/port-to-vector.json +8 -8
  134. package/skills/pixerate-canvas/SKILL.md +11 -1
  135. package/skills/pixerate-image-editor/SKILL.md +19 -64
  136. package/skills/pixerate-image-editor/references/color-management.md +2 -1
  137. package/skills/pixerate-image-editor/references/free-transform.md +12 -0
  138. package/skills/pixerate-image-editor/references/layer-effects.md +10 -0
  139. package/skills/pixerate-image-editor/references/painting.md +17 -0
  140. package/skills/pixerate-image-editor/references/photoshop-files.md +1 -1
  141. package/skills/pixerate-image-editor/references/shapes-and-type.md +14 -0
  142. package/skills/pixerate-image-editor/references/smart-objects.md +10 -0
  143. package/skills/pixerate-paint-editor/SKILL.md +14 -4
  144. package/skills/pixerate-paint-editor/references/brush-facets.md +3 -1
  145. package/skills/pixerate-paint-editor/references/wet-media.md +9 -0
  146. package/skills/pixerate-paint-sketch-to-finish/SKILL.md +1 -0
  147. package/skills/pixerate-vector/SKILL.md +16 -6
  148. package/skills/pixerate-vector/references/best-practices.md +1 -0
  149. package/skills/pixerate-vector/references/commands.md +19 -0
@@ -1,7 +1,51 @@
1
+ import {
2
+ DEFAULT_RETOUCH,
3
+ IDENTITY_CLONE_TRANSFORM,
4
+ RETOUCH_SAMPLES,
5
+ RegionPixelSource,
6
+ RetouchDabStroke,
7
+ SPOT_HEAL_TYPES,
8
+ TONE_RANGES,
9
+ TilePixelSource,
10
+ TransformedPixelSource,
11
+ applyRetouchToTile,
12
+ applyToneToDeepTile,
13
+ boxBlurPixels,
14
+ cloneSamplePoint,
15
+ createPigmentTools,
16
+ dodgeBurn,
17
+ dodgeBurnCurve,
18
+ healPixels,
19
+ isIdentityCloneTransform,
20
+ luma,
21
+ normalizeRetouch,
22
+ perDabStrength,
23
+ pointerPressure,
24
+ pointerStrokeSample,
25
+ pointerStrokeSamples,
26
+ readSourceRegion,
27
+ retouchFilter,
28
+ rgbaViewOfGrey,
29
+ saturationOf,
30
+ smudgeEffect,
31
+ sponge,
32
+ spongeEffect,
33
+ spotHealPixels,
34
+ spotHealWindow,
35
+ toneOf
36
+ } from "../chunk-HVO6XCI4.js";
37
+ import {
38
+ bestOffset,
39
+ contentAwareFill,
40
+ dilateMask,
41
+ maskBounds,
42
+ membraneFill,
43
+ seamlessClone,
44
+ solveMembrane
45
+ } from "../chunk-VWEWY4FY.js";
1
46
  import {
2
47
  BODY_SCATTER,
3
48
  DEFAULT_FLOW,
4
- DEFAULT_RETOUCH,
5
49
  DEFAULT_WET_PAPER,
6
50
  DEFAULT_WET_PARAMS,
7
51
  DRY_EPS,
@@ -16,7 +60,6 @@ import {
16
60
  FLAT,
17
61
  FREE_INTERVAL,
18
62
  HIDE,
19
- IDENTITY_CLONE_TRANSFORM,
20
63
  MASS_CHANNELS,
21
64
  MAX_BATCH,
22
65
  MAX_TILT_ACCEL,
@@ -42,19 +85,12 @@ import {
42
85
  P_SW,
43
86
  P_UX,
44
87
  P_UY,
45
- RETOUCH_SAMPLES,
46
- RegionPixelSource,
47
- RetouchDabStroke,
48
88
  SET_PLANES,
49
89
  SLOT_BYTES,
50
90
  SLOT_PLANES,
51
91
  SLOT_SIDE,
52
- SPOT_HEAL_TYPES,
53
92
  SRGB_TO_LINEAR,
54
93
  STRIP,
55
- TONE_RANGES,
56
- TilePixelSource,
57
- TransformedPixelSource,
58
94
  U_MAX,
59
95
  W9,
60
96
  WET_FLOW_KINDS,
@@ -68,17 +104,10 @@ import {
68
104
  WetWorkerPool,
69
105
  WetWorld,
70
106
  WetWorldError,
71
- applyRetouchToTile,
72
- applyToneToDeepTile,
73
- boxBlurPixels,
74
107
  canShareMemory,
75
- cloneSamplePoint,
76
- createPigmentTools,
77
108
  createWetGpuEngine,
78
109
  dexp,
79
110
  dlog,
80
- dodgeBurn,
81
- dodgeBurnCurve,
82
111
  dpow,
83
112
  dsincos,
84
113
  edgeBits,
@@ -87,71 +116,38 @@ import {
87
116
  filmReflectance,
88
117
  findWebGpu,
89
118
  flowField,
90
- healPixels,
91
- isIdentityCloneTransform,
92
119
  latticeViscosity,
93
120
  linearToSrgb8,
94
121
  loadWetKernel,
95
- luma,
96
122
  moveWetSnapshot,
97
123
  normalizeFlow,
98
- normalizeRetouch,
99
124
  normalizeTilt,
100
125
  normalizeWetParams,
101
126
  packWetParams,
102
- perDabStrength,
103
127
  pigmentColor,
104
128
  pigmentOf,
105
129
  pixelPigment,
106
- pointerPressure,
107
- pointerStrokeSample,
108
- pointerStrokeSamples,
109
- readSourceRegion,
110
- retouchFilter,
111
- rgbaViewOfGrey,
112
- saturationOf,
113
130
  shadeLightTile,
114
131
  shadeTile,
115
- smudgeEffect,
116
- sponge,
117
- spongeEffect,
118
- spotHealPixels,
119
- spotHealWindow,
120
132
  srgbByteToLinear,
121
133
  stepSlotTs,
122
- toneOf,
123
134
  wetGpuSupport,
124
135
  wetSimdSupported,
125
136
  wetSupport
126
- } from "../chunk-XC6DPRYI.js";
127
- import {
128
- bestOffset,
129
- contentAwareFill,
130
- dilateMask,
131
- maskBounds,
132
- membraneFill,
133
- seamlessClone,
134
- solveMembrane
135
- } from "../chunk-VWEWY4FY.js";
137
+ } from "../chunk-GSTSZPSR.js";
136
138
  import {
137
139
  BrushstrokeCache,
138
- GRAIN_PATTERNS,
139
- GRAIN_TILE,
140
- PaperGrain,
141
140
  brushstrokeDataUrl,
142
141
  brushstrokeKey,
143
142
  brushstrokeSamples,
144
143
  brushstrokeStrokeOptions,
145
144
  brushstrokeToCanvas,
146
- grainCatch,
147
- grainHeights,
148
145
  isBrushstrokeBrush,
149
146
  paintPathStroke,
150
147
  pathStrokeCoverage,
151
148
  pathStrokeDabs,
152
- renderBrushstroke,
153
- strokeGrainCatch
154
- } from "../chunk-TXFWZ5ZJ.js";
149
+ renderBrushstroke
150
+ } from "../chunk-W6JDUXP3.js";
155
151
  import {
156
152
  CoverageMap,
157
153
  DEFAULT_BLENDER,
@@ -162,6 +158,8 @@ import {
162
158
  DEFAULT_SMUDGE,
163
159
  DabWalker,
164
160
  EMPTY_MIXER_LOAD,
161
+ GRAIN_PATTERNS,
162
+ GRAIN_TILE,
165
163
  MAX_BRUSH_SIZE,
166
164
  MIXER_DRAIN,
167
165
  MIXER_PICKUP_RATE,
@@ -182,6 +180,7 @@ import {
182
180
  PaintExchange,
183
181
  PaintGradientSampler,
184
182
  PaintSourceError,
183
+ PaperGrain,
185
184
  SmudgeTip,
186
185
  StrokeCoverage,
187
186
  TIP_GRADIENT_STEPS,
@@ -198,6 +197,8 @@ import {
198
197
  dabRect,
199
198
  exchangeRates,
200
199
  gradientDabColor,
200
+ grainCatch,
201
+ grainHeights,
201
202
  hexToPaintRgb,
202
203
  isGradientPaint,
203
204
  loadMixer,
@@ -220,12 +221,13 @@ import {
220
221
  scalePaintGradient,
221
222
  smoothPoints,
222
223
  solidPaint,
224
+ strokeGrainCatch,
223
225
  tipFalloff,
224
226
  tipReach,
225
227
  tipShape,
226
228
  updatePaintGradientStop,
227
229
  walkDabs
228
- } from "../chunk-GCVFEPJG.js";
230
+ } from "../chunk-ACTHSQOI.js";
229
231
  import {
230
232
  TileableNoise,
231
233
  hash2,
@@ -239,7 +241,6 @@ import {
239
241
  BRUSHSTROKE_MIN_SCALE,
240
242
  brushstrokeScaleBucket
241
243
  } from "../chunk-ODBT55Q7.js";
242
- import "../chunk-OTTT5N3K.js";
243
244
  import {
244
245
  PIGMENT_BANDS,
245
246
  PIGMENT_LAMBDA_MIN,
@@ -253,6 +254,7 @@ import {
253
254
  rgbToReflectance,
254
255
  setPigmentColor
255
256
  } from "../chunk-IRSTHLQQ.js";
257
+ import "../chunk-OTTT5N3K.js";
256
258
  import "../chunk-HVVR5PZW.js";
257
259
  import "../chunk-QGHEDC7B.js";
258
260
  export {
@@ -2,17 +2,27 @@
2
2
  * The shared brush library's agent tools for a paint editor (`createPaintBrushLibraryToolProvider`),
3
3
  * with `preview_brush` painted by this editor.
4
4
  */
5
+ import type { BrushLibrary } from '../brushes/library.cjs';
6
+ import type { StickerArtLookup } from './sticker-art.cjs';
5
7
  import { type BrushLibraryToolProviderOptions, type BrushPreviewRenderer } from '../brushes/tools.cjs';
6
8
  import type { AgentToolProvider } from '../tools/registry.cjs';
7
9
  import type { PaintEditorController } from './controller.cjs';
8
10
  import { type PaperSettings } from './paper.cjs';
9
11
  export type PaintBrushLibraryToolProviderOptions = Omit<BrushLibraryToolProviderOptions, 'renderPreview'>;
12
+ /** Where a preview renderer finds a brush's image sources (and sticker art). */
13
+ export interface PaintBrushPreviewOptions {
14
+ /** Image sources are read from this library before each preview that needs them. */
15
+ library?: Pick<BrushLibrary, 'getSource'>;
16
+ /** Art for sticker stamp tips (and anything else not in the library), read on every call. */
17
+ stampArt?: () => StickerArtLookup | undefined;
18
+ }
10
19
  /**
11
20
  * A brush preview renderer (`BrushPreviewRenderer`, as `preview_brush` and `BrushLibraryEditor`
12
21
  * take) that paints the test stroke with the paint engine on `paper` (read on every call; default
13
- * the default paper). Any brush the paint editor renders, so also the image editor's.
22
+ * the default paper). Any brush the paint editor renders, so also the image editor's. With
23
+ * `options.library`, image tips and image grain are drawn from its sources.
14
24
  */
15
- export declare function paintBrushPreviewRenderer(paper?: () => PaperSettings): BrushPreviewRenderer;
25
+ export declare function paintBrushPreviewRenderer(paper?: () => PaperSettings, options?: PaintBrushPreviewOptions): BrushPreviewRenderer;
16
26
  /**
17
27
  * The brush library tools for a paint editor (`@pixerate/editor/brushes`' provider on the
18
28
  * editor's `brushLibrary`, `PAINT_PROFILE`), with `preview_brush` painting the test stroke on the
@@ -2,17 +2,27 @@
2
2
  * The shared brush library's agent tools for a paint editor (`createPaintBrushLibraryToolProvider`),
3
3
  * with `preview_brush` painted by this editor.
4
4
  */
5
+ import type { BrushLibrary } from '../brushes/library.js';
6
+ import type { StickerArtLookup } from './sticker-art.js';
5
7
  import { type BrushLibraryToolProviderOptions, type BrushPreviewRenderer } from '../brushes/tools.js';
6
8
  import type { AgentToolProvider } from '../tools/registry.js';
7
9
  import type { PaintEditorController } from './controller.js';
8
10
  import { type PaperSettings } from './paper.js';
9
11
  export type PaintBrushLibraryToolProviderOptions = Omit<BrushLibraryToolProviderOptions, 'renderPreview'>;
12
+ /** Where a preview renderer finds a brush's image sources (and sticker art). */
13
+ export interface PaintBrushPreviewOptions {
14
+ /** Image sources are read from this library before each preview that needs them. */
15
+ library?: Pick<BrushLibrary, 'getSource'>;
16
+ /** Art for sticker stamp tips (and anything else not in the library), read on every call. */
17
+ stampArt?: () => StickerArtLookup | undefined;
18
+ }
10
19
  /**
11
20
  * A brush preview renderer (`BrushPreviewRenderer`, as `preview_brush` and `BrushLibraryEditor`
12
21
  * take) that paints the test stroke with the paint engine on `paper` (read on every call; default
13
- * the default paper). Any brush the paint editor renders, so also the image editor's.
22
+ * the default paper). Any brush the paint editor renders, so also the image editor's. With
23
+ * `options.library`, image tips and image grain are drawn from its sources.
14
24
  */
15
- export declare function paintBrushPreviewRenderer(paper?: () => PaperSettings): BrushPreviewRenderer;
25
+ export declare function paintBrushPreviewRenderer(paper?: () => PaperSettings, options?: PaintBrushPreviewOptions): BrushPreviewRenderer;
16
26
  /**
17
27
  * The brush library tools for a paint editor (`@pixerate/editor/brushes`' provider on the
18
28
  * editor's `brushLibrary`, `PAINT_PROFILE`), with `preview_brush` painting the test stroke on the
@@ -156,7 +156,31 @@ export interface BrushDynamics {
156
156
  opacityJitter: number;
157
157
  /** Random offset across the stroke in diameters, 0..4 (default 0). */
158
158
  scatter: number;
159
+ /** Dabs laid at each spacing step, 1..16, each with its own jitter (missing: 1). */
160
+ count?: number;
161
+ /** Mirror each dab at random across these axes (missing: `none`). */
162
+ flip?: DabFlip;
159
163
  }
164
+ /** Random mirroring of dabs. */
165
+ export type DabFlip = 'none' | 'x' | 'y' | 'xy';
166
+ export declare const DAB_FLIPS: readonly DabFlip[];
167
+ export type TipGrainMode = 'moving' | 'texturised';
168
+ export declare const TIP_GRAIN_MODES: readonly TipGrainMode[];
169
+ /** Texture inside the tip (dab engines): each dab's coverage is multiplied by it. */
170
+ export interface TipGrainSettings {
171
+ /** A grain pattern (`rough`, `canvas`…) or an image source `source:<id>`. */
172
+ source: string;
173
+ /** `texturised` (default): fixed to the canvas; `moving`: rolls along with the tip. */
174
+ mode: TipGrainMode;
175
+ /** 0.05..20: 1 the source's own size (default 1). */
176
+ scale: number;
177
+ /** 0..1: how much it takes out of the dab (default 0.6). */
178
+ depth: number;
179
+ /** 0..3 around the middle (default 1). */
180
+ contrast: number;
181
+ invert: boolean;
182
+ }
183
+ export declare const DEFAULT_TIP_GRAIN: Readonly<Omit<TipGrainSettings, 'source'>>;
160
184
  export declare const DEFAULT_DYNAMICS: Readonly<BrushDynamics>;
161
185
  export interface PaintBrush {
162
186
  /** Library id (lowercase letters, digits and dashes). */
@@ -202,6 +226,8 @@ export interface PaintBrush {
202
226
  stamp: string | null;
203
227
  /** Dab engine: spray marks. Each dab lays a seeded scatter of droplets across the tip; `null` (default): one mark per dab. */
204
228
  spray: SpraySettings | null;
229
+ /** Dab engines: texture inside the tip (missing: none). Recorded with the stroke, source ref included, so replays match. */
230
+ tipGrain?: TipGrainSettings;
205
231
  /**
206
232
  * The brush's own gradient paint (`@pixerate/editor/paint` `PaintGradientSource`), used instead
207
233
  * of the editor's paint; `null` (default): the editor's paint. Stops may be `paint` / `secondary`
@@ -228,8 +254,10 @@ export interface SpraySettings {
228
254
  size: number;
229
255
  }
230
256
  export declare const DEFAULT_SPRAY: Readonly<SpraySettings>;
231
- export type PaintBrushInput = Partial<Omit<PaintBrush, 'tip' | 'dynamics' | 'mixer' | 'behavior' | 'blender' | 'smudge' | 'wet' | 'impasto' | 'particle' | 'bristle' | 'sticker' | 'paint' | 'light' | 'spray'>> & {
257
+ export type PaintBrushInput = Partial<Omit<PaintBrush, 'tip' | 'dynamics' | 'mixer' | 'behavior' | 'blender' | 'smudge' | 'wet' | 'impasto' | 'particle' | 'bristle' | 'sticker' | 'paint' | 'light' | 'spray' | 'tipGrain'>> & {
232
258
  spray?: Partial<SpraySettings> | null;
259
+ /** Tip grain (`null` removes it). */
260
+ tipGrain?: Partial<TipGrainSettings> | null;
233
261
  light?: Partial<LightSettings>;
234
262
  /** A gradient (or `null` for the editor's paint); a plain colour source clears it. */
235
263
  paint?: PaintSource | null;
@@ -156,7 +156,31 @@ export interface BrushDynamics {
156
156
  opacityJitter: number;
157
157
  /** Random offset across the stroke in diameters, 0..4 (default 0). */
158
158
  scatter: number;
159
+ /** Dabs laid at each spacing step, 1..16, each with its own jitter (missing: 1). */
160
+ count?: number;
161
+ /** Mirror each dab at random across these axes (missing: `none`). */
162
+ flip?: DabFlip;
159
163
  }
164
+ /** Random mirroring of dabs. */
165
+ export type DabFlip = 'none' | 'x' | 'y' | 'xy';
166
+ export declare const DAB_FLIPS: readonly DabFlip[];
167
+ export type TipGrainMode = 'moving' | 'texturised';
168
+ export declare const TIP_GRAIN_MODES: readonly TipGrainMode[];
169
+ /** Texture inside the tip (dab engines): each dab's coverage is multiplied by it. */
170
+ export interface TipGrainSettings {
171
+ /** A grain pattern (`rough`, `canvas`…) or an image source `source:<id>`. */
172
+ source: string;
173
+ /** `texturised` (default): fixed to the canvas; `moving`: rolls along with the tip. */
174
+ mode: TipGrainMode;
175
+ /** 0.05..20: 1 the source's own size (default 1). */
176
+ scale: number;
177
+ /** 0..1: how much it takes out of the dab (default 0.6). */
178
+ depth: number;
179
+ /** 0..3 around the middle (default 1). */
180
+ contrast: number;
181
+ invert: boolean;
182
+ }
183
+ export declare const DEFAULT_TIP_GRAIN: Readonly<Omit<TipGrainSettings, 'source'>>;
160
184
  export declare const DEFAULT_DYNAMICS: Readonly<BrushDynamics>;
161
185
  export interface PaintBrush {
162
186
  /** Library id (lowercase letters, digits and dashes). */
@@ -202,6 +226,8 @@ export interface PaintBrush {
202
226
  stamp: string | null;
203
227
  /** Dab engine: spray marks. Each dab lays a seeded scatter of droplets across the tip; `null` (default): one mark per dab. */
204
228
  spray: SpraySettings | null;
229
+ /** Dab engines: texture inside the tip (missing: none). Recorded with the stroke, source ref included, so replays match. */
230
+ tipGrain?: TipGrainSettings;
205
231
  /**
206
232
  * The brush's own gradient paint (`@pixerate/editor/paint` `PaintGradientSource`), used instead
207
233
  * of the editor's paint; `null` (default): the editor's paint. Stops may be `paint` / `secondary`
@@ -228,8 +254,10 @@ export interface SpraySettings {
228
254
  size: number;
229
255
  }
230
256
  export declare const DEFAULT_SPRAY: Readonly<SpraySettings>;
231
- export type PaintBrushInput = Partial<Omit<PaintBrush, 'tip' | 'dynamics' | 'mixer' | 'behavior' | 'blender' | 'smudge' | 'wet' | 'impasto' | 'particle' | 'bristle' | 'sticker' | 'paint' | 'light' | 'spray'>> & {
257
+ export type PaintBrushInput = Partial<Omit<PaintBrush, 'tip' | 'dynamics' | 'mixer' | 'behavior' | 'blender' | 'smudge' | 'wet' | 'impasto' | 'particle' | 'bristle' | 'sticker' | 'paint' | 'light' | 'spray' | 'tipGrain'>> & {
232
258
  spray?: Partial<SpraySettings> | null;
259
+ /** Tip grain (`null` removes it). */
260
+ tipGrain?: Partial<TipGrainSettings> | null;
233
261
  light?: Partial<LightSettings>;
234
262
  /** A gradient (or `null` for the editor's paint); a plain colour source clears it. */
235
263
  paint?: PaintSource | null;
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Brush sources the paint engine can draw with: the brush library's and the open painting's, by
3
+ * id. Strokes read them synchronously, as they read sticker art (`StickerArtLookup`): a stamp tip
4
+ * `source:<id>` and an image tip grain both take the source's mask as alpha. Each mask is decoded
5
+ * the first time it is drawn.
6
+ */
7
+ import { type BrushSource } from '../brushes/sources.cjs';
8
+ import type { StickerArtLookup } from './sticker-art.cjs';
9
+ export declare class BrushSourceArtCache {
10
+ private readonly sources;
11
+ private readonly art;
12
+ /** Adds or replaces sources (a replaced image is decoded again). */
13
+ set(sources: Iterable<BrushSource>): void;
14
+ /** The source of an id, if known. */
15
+ source(id: string): BrushSource | undefined;
16
+ /** Every known source. */
17
+ all(): BrushSource[];
18
+ /** The art of a `source:<id>` ref (alpha = the mask), or `undefined` when the source is unknown or its image can't be read. */
19
+ get: StickerArtLookup;
20
+ /** A lookup that reads sources from here and every other ref from `stickers`. */
21
+ with(stickers: StickerArtLookup): StickerArtLookup;
22
+ }
23
+ /** The ids of the sources an engine brush draws with: its stamp tip, its tip grain and its particle stamps. */
24
+ export declare function engineBrushSourceIds(brush: {
25
+ stamp: string | null;
26
+ tipGrain?: {
27
+ source: string;
28
+ };
29
+ particle?: {
30
+ dotTextures: readonly string[];
31
+ };
32
+ }): string[];
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Brush sources the paint engine can draw with: the brush library's and the open painting's, by
3
+ * id. Strokes read them synchronously, as they read sticker art (`StickerArtLookup`): a stamp tip
4
+ * `source:<id>` and an image tip grain both take the source's mask as alpha. Each mask is decoded
5
+ * the first time it is drawn.
6
+ */
7
+ import { type BrushSource } from '../brushes/sources.js';
8
+ import type { StickerArtLookup } from './sticker-art.js';
9
+ export declare class BrushSourceArtCache {
10
+ private readonly sources;
11
+ private readonly art;
12
+ /** Adds or replaces sources (a replaced image is decoded again). */
13
+ set(sources: Iterable<BrushSource>): void;
14
+ /** The source of an id, if known. */
15
+ source(id: string): BrushSource | undefined;
16
+ /** Every known source. */
17
+ all(): BrushSource[];
18
+ /** The art of a `source:<id>` ref (alpha = the mask), or `undefined` when the source is unknown or its image can't be read. */
19
+ get: StickerArtLookup;
20
+ /** A lookup that reads sources from here and every other ref from `stickers`. */
21
+ with(stickers: StickerArtLookup): StickerArtLookup;
22
+ }
23
+ /** The ids of the sources an engine brush draws with: its stamp tip, its tip grain and its particle stamps. */
24
+ export declare function engineBrushSourceIds(brush: {
25
+ stamp: string | null;
26
+ tipGrain?: {
27
+ source: string;
28
+ };
29
+ particle?: {
30
+ dotTextures: readonly string[];
31
+ };
32
+ }): string[];
@@ -39,7 +39,8 @@ import { type PaintGuides, type PerspectiveGuide, type ReferenceImage, type Symm
39
39
  import { MixingPad, type MixingPadTool, type PadMixOptions } from './mixing-pad.cjs';
40
40
  import { type Stencil, type StencilInput } from './stencils.cjs';
41
41
  import { type Sticker } from './stickers.cjs';
42
- import { type StickerRasterizer } from './sticker-art.cjs';
42
+ import { type StickerArtLookup, type StickerRasterizer } from './sticker-art.cjs';
43
+ import { BrushSourceArtCache } from './brush-source-art.cjs';
43
44
  import { StickersSlot } from '../stickers/helpers.cjs';
44
45
  import type { StickerProvider, StickerRef } from '../stickers/types.cjs';
45
46
  import { type LightSpill } from './light.cjs';
@@ -445,6 +446,10 @@ export declare class PaintEditorController {
445
446
  /** The sticker library slot (see `setStickersProvider`). */
446
447
  readonly stickers: StickersSlot;
447
448
  private readonly stickerArt;
449
+ /** Image sources strokes draw with: the brush library's and the open painting's (saved with it). */
450
+ readonly brushSources: BrushSourceArtCache;
451
+ /** Art for stamp tips and tip grain: image sources from `brushSources`, stickers from the sticker library. */
452
+ readonly stampArt: StickerArtLookup;
448
453
  private readonly rasterizeSticker;
449
454
  private readonly effectsRenderer;
450
455
  private paperEffectNodeCache;
@@ -478,10 +483,12 @@ export declare class PaintEditorController {
478
483
  withOrigin<T>(origin: string, fn: () => T): T;
479
484
  /**
480
485
  * Runs `fn` as one undo step named `label`: every change it makes (strokes, fills, new layers) is
481
- * undone together. Wet paint can't be grouped. Nested groups join the outer one. If `fn` throws,
482
- * its changes are put back and nothing is recorded.
486
+ * undone together. When `fn` returns a promise, the group holds until it settles; until then other
487
+ * changes (the user's strokes, undo) are refused, except those `fn` makes through `within`, so
488
+ * nothing else lands in (or is lost with) the group's step. Nested groups join the outer one. If
489
+ * `fn` throws or rejects, its changes are put back and nothing is recorded.
483
490
  */
484
- group<T>(label: string, fn: () => T): T;
491
+ group<T>(label: string, fn: (within: <U>(step: () => U) => U) => T): T;
485
492
  /**
486
493
  * What `fn` would paint, without changing anything: it runs on a new empty layer (above the
487
494
  * active layer, another one, or at the bottom), and the layer's pixels and the picture with them
@@ -39,7 +39,8 @@ import { type PaintGuides, type PerspectiveGuide, type ReferenceImage, type Symm
39
39
  import { MixingPad, type MixingPadTool, type PadMixOptions } from './mixing-pad.js';
40
40
  import { type Stencil, type StencilInput } from './stencils.js';
41
41
  import { type Sticker } from './stickers.js';
42
- import { type StickerRasterizer } from './sticker-art.js';
42
+ import { type StickerArtLookup, type StickerRasterizer } from './sticker-art.js';
43
+ import { BrushSourceArtCache } from './brush-source-art.js';
43
44
  import { StickersSlot } from '../stickers/helpers.js';
44
45
  import type { StickerProvider, StickerRef } from '../stickers/types.js';
45
46
  import { type LightSpill } from './light.js';
@@ -445,6 +446,10 @@ export declare class PaintEditorController {
445
446
  /** The sticker library slot (see `setStickersProvider`). */
446
447
  readonly stickers: StickersSlot;
447
448
  private readonly stickerArt;
449
+ /** Image sources strokes draw with: the brush library's and the open painting's (saved with it). */
450
+ readonly brushSources: BrushSourceArtCache;
451
+ /** Art for stamp tips and tip grain: image sources from `brushSources`, stickers from the sticker library. */
452
+ readonly stampArt: StickerArtLookup;
448
453
  private readonly rasterizeSticker;
449
454
  private readonly effectsRenderer;
450
455
  private paperEffectNodeCache;
@@ -478,10 +483,12 @@ export declare class PaintEditorController {
478
483
  withOrigin<T>(origin: string, fn: () => T): T;
479
484
  /**
480
485
  * Runs `fn` as one undo step named `label`: every change it makes (strokes, fills, new layers) is
481
- * undone together. Wet paint can't be grouped. Nested groups join the outer one. If `fn` throws,
482
- * its changes are put back and nothing is recorded.
486
+ * undone together. When `fn` returns a promise, the group holds until it settles; until then other
487
+ * changes (the user's strokes, undo) are refused, except those `fn` makes through `within`, so
488
+ * nothing else lands in (or is lost with) the group's step. Nested groups join the outer one. If
489
+ * `fn` throws or rejects, its changes are put back and nothing is recorded.
483
490
  */
484
- group<T>(label: string, fn: () => T): T;
491
+ group<T>(label: string, fn: (within: <U>(step: () => U) => U) => T): T;
485
492
  /**
486
493
  * What `fn` would paint, without changing anything: it runs on a new empty layer (above the
487
494
  * active layer, another one, or at the bottom), and the layer's pixels and the picture with them
@@ -76,6 +76,8 @@ export declare class PaintDabStroke {
76
76
  private lastFed;
77
77
  /** The stamp tip's shape (dab brushes), or `null` for the round computed tip. */
78
78
  private readonly stamp;
79
+ /** The tip's own grain, or `null`. */
80
+ private readonly tipGrain;
79
81
  constructor(brush: PaintBrush, options: PaintDabStrokeOptions);
80
82
  /** What copy 0's brush carries after the dabs so far (mixer and wet-capable dab brushes). */
81
83
  get load(): MixerLoad | null;
@@ -76,6 +76,8 @@ export declare class PaintDabStroke {
76
76
  private lastFed;
77
77
  /** The stamp tip's shape (dab brushes), or `null` for the round computed tip. */
78
78
  private readonly stamp;
79
+ /** The tip's own grain, or `null`. */
80
+ private readonly tipGrain;
79
81
  constructor(brush: PaintBrush, options: PaintDabStrokeOptions);
80
82
  /** What copy 0's brush carries after the dabs so far (mixer and wet-capable dab brushes). */
81
83
  get load(): MixerLoad | null;
@@ -88,6 +88,8 @@ export interface PenDab extends Dab {
88
88
  lean: number;
89
89
  /** Pen speed (px/ms), or `null` when the samples carry no time. */
90
90
  speed: number | null;
91
+ /** Mirrored across the tip's x axis (bit 1) and y axis (bit 2), from `dynamics.flip`; 0 or missing: not mirrored. */
92
+ flip?: number;
91
93
  }
92
94
  /**
93
95
  * Walks pen samples into dabs, incrementally (any chunking gives the same dabs). Dab angles are in
@@ -115,6 +117,8 @@ export declare class PenDabWalker {
115
117
  private dab;
116
118
  push(p: PenPoint, out: PenDab[]): void;
117
119
  finish(out: PenDab[]): void;
120
+ /** The dabs of one spacing step: `dynamics.count` of them, each with its own index and so its own jitter. */
121
+ private lay;
118
122
  }
119
123
  export interface DryStrokeOptions {
120
124
  /** The paper's dry height field, or `null` for no grain. */
@@ -127,7 +131,10 @@ export interface DryStrokeOptions {
127
131
  copies?: readonly StrokeCopy[];
128
132
  /** Effect paint: each pixel takes its colour (and alpha) from these canvas-sized pixels. */
129
133
  effect?: EffectPaintPixels | null;
130
- /** Loaded sticker art, for a stamp tip of a sticker from the sticker library (`brush.stamp`); without it such a tip paints round. */
134
+ /**
135
+ * Loaded art for a stamp tip of a sticker or an image source (`brush.stamp`) and for an image
136
+ * tip grain (`brush.tipGrain.source`); without it such a tip paints round, and the grain is left out.
137
+ */
131
138
  stampArt?: StickerArtLookup;
132
139
  }
133
140
  /**
@@ -149,13 +156,15 @@ export declare class DryStroke {
149
156
  private lastFed;
150
157
  /** The stamp tip's shape, or `null` for the round computed tip. */
151
158
  private readonly stamp;
159
+ /** The tip's own grain, or `null`. */
160
+ private readonly tipGrain;
152
161
  constructor(brush: PaintBrush, options: DryStrokeOptions);
153
162
  /** Feeds raw pen samples; returns the document rectangles the new dabs touched. */
154
163
  push(points: readonly PenPoint[]): RasterRect[];
155
164
  /** Ends the stroke: the smoothed path catches up with the last raw sample; a single tap paints one dab. */
156
165
  finish(): RasterRect[];
157
166
  private paint;
158
- /** Lays one mark (a dab, or a spray droplet of dab `d`): the round tip or the stamp, the paper grain, effect paint. */
167
+ /** Lays one mark (a dab, or a spray droplet of dab `d`): the round tip or the stamp, the tip grain, the paper grain, effect paint. */
159
168
  private mark;
160
169
  }
161
170
  /** The shared engine's tip for the Mixer Brush engine (it smooths and walks by itself, so smoothing is applied before). */
@@ -88,6 +88,8 @@ export interface PenDab extends Dab {
88
88
  lean: number;
89
89
  /** Pen speed (px/ms), or `null` when the samples carry no time. */
90
90
  speed: number | null;
91
+ /** Mirrored across the tip's x axis (bit 1) and y axis (bit 2), from `dynamics.flip`; 0 or missing: not mirrored. */
92
+ flip?: number;
91
93
  }
92
94
  /**
93
95
  * Walks pen samples into dabs, incrementally (any chunking gives the same dabs). Dab angles are in
@@ -115,6 +117,8 @@ export declare class PenDabWalker {
115
117
  private dab;
116
118
  push(p: PenPoint, out: PenDab[]): void;
117
119
  finish(out: PenDab[]): void;
120
+ /** The dabs of one spacing step: `dynamics.count` of them, each with its own index and so its own jitter. */
121
+ private lay;
118
122
  }
119
123
  export interface DryStrokeOptions {
120
124
  /** The paper's dry height field, or `null` for no grain. */
@@ -127,7 +131,10 @@ export interface DryStrokeOptions {
127
131
  copies?: readonly StrokeCopy[];
128
132
  /** Effect paint: each pixel takes its colour (and alpha) from these canvas-sized pixels. */
129
133
  effect?: EffectPaintPixels | null;
130
- /** Loaded sticker art, for a stamp tip of a sticker from the sticker library (`brush.stamp`); without it such a tip paints round. */
134
+ /**
135
+ * Loaded art for a stamp tip of a sticker or an image source (`brush.stamp`) and for an image
136
+ * tip grain (`brush.tipGrain.source`); without it such a tip paints round, and the grain is left out.
137
+ */
131
138
  stampArt?: StickerArtLookup;
132
139
  }
133
140
  /**
@@ -149,13 +156,15 @@ export declare class DryStroke {
149
156
  private lastFed;
150
157
  /** The stamp tip's shape, or `null` for the round computed tip. */
151
158
  private readonly stamp;
159
+ /** The tip's own grain, or `null`. */
160
+ private readonly tipGrain;
152
161
  constructor(brush: PaintBrush, options: DryStrokeOptions);
153
162
  /** Feeds raw pen samples; returns the document rectangles the new dabs touched. */
154
163
  push(points: readonly PenPoint[]): RasterRect[];
155
164
  /** Ends the stroke: the smoothed path catches up with the last raw sample; a single tap paints one dab. */
156
165
  finish(): RasterRect[];
157
166
  private paint;
158
- /** Lays one mark (a dab, or a spray droplet of dab `d`): the round tip or the stamp, the paper grain, effect paint. */
167
+ /** Lays one mark (a dab, or a spray droplet of dab `d`): the round tip or the stamp, the tip grain, the paper grain, effect paint. */
159
168
  private mark;
160
169
  }
161
170
  /** The shared engine's tip for the Mixer Brush engine (it smooths and walks by itself, so smoothing is applied before). */