@pixerate/editor 0.248.0 → 0.250.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 (122) hide show
  1. package/README.md +1 -0
  2. package/dist/animation-editor/index.cjs +118 -114
  3. package/dist/animation-editor/index.js +11 -7
  4. package/dist/{brushstrokeRender-QLCXROJK.js → brushstrokeRender-2FHFLSEG.js} +8 -4
  5. package/dist/{brushstrokeRender-DTDPFBLC.cjs → brushstrokeRender-QGRXOKDA.cjs} +15 -11
  6. package/dist/canvas/index.cjs +71 -15
  7. package/dist/canvas/index.d.cts +1 -0
  8. package/dist/canvas/index.d.ts +1 -0
  9. package/dist/canvas/index.js +58 -2
  10. package/dist/canvas/stickers.d.cts +35 -0
  11. package/dist/canvas/stickers.d.ts +35 -0
  12. package/dist/{chunk-RXZL4NG5.js → chunk-226QDRO3.js} +1 -1
  13. package/dist/{chunk-SC2RZ5EF.js → chunk-2VJAVXLI.js} +2 -2
  14. package/dist/{chunk-OLNIPTB3.cjs → chunk-2VX55NFM.cjs} +1 -320
  15. package/dist/chunk-3K6HWEXZ.cjs +92 -0
  16. package/dist/{chunk-UOOK7HTX.js → chunk-3PPJRMIG.js} +1 -1
  17. package/dist/{chunk-ZFSLEOSQ.js → chunk-3TWOCSCY.js} +11 -9
  18. package/dist/chunk-4D6KP5BV.js +92 -0
  19. package/dist/chunk-4JNWA3VT.cjs +302 -0
  20. package/dist/{chunk-L3JFOTBQ.js → chunk-5E2Q7ZHI.js} +1 -1
  21. package/dist/{chunk-2ONK3ERD.cjs → chunk-75K3W4D6.cjs} +20 -20
  22. package/dist/{chunk-AU6MWQKZ.js → chunk-ABL7IWFZ.js} +1 -1
  23. package/dist/chunk-ATK6ABN3.cjs +303 -0
  24. package/dist/{chunk-7T7JWTVE.cjs → chunk-BOHDJJ2O.cjs} +8 -8
  25. package/dist/{chunk-2PBZBRP5.js → chunk-D5KGAO4Z.js} +10 -92
  26. package/dist/{chunk-HB4ICNNA.cjs → chunk-DPYAO5U6.cjs} +42 -42
  27. package/dist/{chunk-6G6ZDDDB.cjs → chunk-GT77U7QG.cjs} +303 -149
  28. package/dist/{chunk-PQ3H2AAN.cjs → chunk-I7NJPHWV.cjs} +122 -204
  29. package/dist/{chunk-42TWUPNJ.js → chunk-IRSTHLQQ.js} +1 -320
  30. package/dist/{chunk-GHCSC2WP.cjs → chunk-ISIO63Q5.cjs} +21 -15
  31. package/dist/{chunk-OFH6Q67U.js → chunk-JA57JIT5.js} +9 -3
  32. package/dist/{chunk-VMROIWLL.cjs → chunk-KBYB7OWB.cjs} +3 -3
  33. package/dist/{chunk-Q2HA52V4.js → chunk-KDLBJ6QR.js} +2 -2
  34. package/dist/{chunk-WVS5KQDH.cjs → chunk-M2VKFE5L.cjs} +246 -244
  35. package/dist/{chunk-5GLYUSNT.js → chunk-NOHJP5TK.js} +1 -1
  36. package/dist/{chunk-XNRBMYNB.js → chunk-NTRAVM2I.js} +1 -1
  37. package/dist/{chunk-VNBUDVD4.js → chunk-OTEPAQJX.js} +228 -74
  38. package/dist/chunk-OTTT5N3K.js +322 -0
  39. package/dist/{chunk-QOBCBGGI.cjs → chunk-QKXO6JPP.cjs} +14 -14
  40. package/dist/{chunk-NZ3O3A5C.js → chunk-SMSGP2HQ.js} +1 -1
  41. package/dist/chunk-SZTI6EER.js +13 -0
  42. package/dist/chunk-U4NUOKBT.js +303 -0
  43. package/dist/chunk-U67EN7GG.cjs +13 -0
  44. package/dist/chunk-W5M3J7PV.cjs +322 -0
  45. package/dist/{chunk-4P6H35HU.js → chunk-WA44NKPF.js} +2 -2
  46. package/dist/chunk-WKH5ZAUA.js +302 -0
  47. package/dist/{chunk-L6REDLNB.cjs → chunk-WPUXGDH4.cjs} +7 -7
  48. package/dist/{chunk-P3NIPIKS.js → chunk-WQCNC4DK.js} +1 -1
  49. package/dist/{chunk-IBDU6EGZ.cjs → chunk-X7WRL5ZZ.cjs} +35 -35
  50. package/dist/{chunk-XWTRATIM.cjs → chunk-YM6ZBTXG.cjs} +23 -23
  51. package/dist/{chunk-TPWB4Y6L.cjs → chunk-YW43M56C.cjs} +1 -1
  52. package/dist/{chunk-K5DS2JTA.cjs → chunk-Z3BRH4JK.cjs} +6 -6
  53. package/dist/{chunk-XNZFVYC2.cjs → chunk-ZBCT5MEA.cjs} +7 -7
  54. package/dist/effects/helpers.d.cts +6 -0
  55. package/dist/effects/helpers.d.ts +6 -0
  56. package/dist/effects/index.cjs +62 -60
  57. package/dist/effects/index.js +5 -3
  58. package/dist/effects/tools.d.cts +6 -0
  59. package/dist/effects/tools.d.ts +6 -0
  60. package/dist/image-editor/effects.d.cts +1 -1
  61. package/dist/image-editor/effects.d.ts +1 -1
  62. package/dist/image-editor/index.cjs +1097 -1069
  63. package/dist/image-editor/index.d.cts +1 -0
  64. package/dist/image-editor/index.d.ts +1 -0
  65. package/dist/image-editor/index.js +58 -30
  66. package/dist/image-editor/stickers.d.cts +9 -0
  67. package/dist/image-editor/stickers.d.ts +9 -0
  68. package/dist/paint/index.cjs +8 -5
  69. package/dist/paint/index.js +13 -10
  70. package/dist/paint-editor/controller.d.cts +37 -1
  71. package/dist/paint-editor/controller.d.ts +37 -1
  72. package/dist/paint-editor/index.cjs +753 -609
  73. package/dist/paint-editor/index.d.cts +3 -0
  74. package/dist/paint-editor/index.d.ts +3 -0
  75. package/dist/paint-editor/index.js +187 -43
  76. package/dist/paint-editor/sticker-art.d.cts +55 -0
  77. package/dist/paint-editor/sticker-art.d.ts +55 -0
  78. package/dist/paint-editor/stickers.d.cts +30 -17
  79. package/dist/paint-editor/stickers.d.ts +30 -17
  80. package/dist/paint-editor/stroke.d.cts +4 -0
  81. package/dist/paint-editor/stroke.d.ts +4 -0
  82. package/dist/paint-editor/ui.d.cts +10 -2
  83. package/dist/paint-editor/ui.d.ts +10 -2
  84. package/dist/raster/index.cjs +6 -4
  85. package/dist/raster/index.js +12 -10
  86. package/dist/stickers/browser.d.cts +48 -0
  87. package/dist/stickers/browser.d.ts +48 -0
  88. package/dist/stickers/combine.d.cts +10 -0
  89. package/dist/stickers/combine.d.ts +10 -0
  90. package/dist/stickers/conformance.d.cts +18 -0
  91. package/dist/stickers/conformance.d.ts +18 -0
  92. package/dist/stickers/editor.d.cts +14 -0
  93. package/dist/stickers/editor.d.ts +14 -0
  94. package/dist/stickers/errors.d.cts +6 -0
  95. package/dist/stickers/errors.d.ts +6 -0
  96. package/dist/stickers/fake.d.cts +16 -0
  97. package/dist/stickers/fake.d.ts +16 -0
  98. package/dist/stickers/helpers.d.cts +51 -0
  99. package/dist/stickers/helpers.d.ts +51 -0
  100. package/dist/stickers/index.cjs +337 -0
  101. package/dist/stickers/index.d.cts +16 -0
  102. package/dist/stickers/index.d.ts +16 -0
  103. package/dist/stickers/index.js +337 -0
  104. package/dist/stickers/stamps.d.cts +13 -0
  105. package/dist/stickers/stamps.d.ts +13 -0
  106. package/dist/stickers/tools.d.cts +81 -0
  107. package/dist/stickers/tools.d.ts +81 -0
  108. package/dist/stickers/types.d.cts +123 -0
  109. package/dist/stickers/types.d.ts +123 -0
  110. package/dist/vector/index.cjs +1018 -981
  111. package/dist/vector/index.d.cts +1 -0
  112. package/dist/vector/index.d.ts +1 -0
  113. package/dist/vector/index.js +44 -7
  114. package/dist/vector/stickers.d.cts +11 -0
  115. package/dist/vector/stickers.d.ts +11 -0
  116. package/dist/video-editor/index.cjs +344 -344
  117. package/dist/video-editor/index.js +4 -4
  118. package/package.json +11 -1
  119. package/skills/README.md +1 -0
  120. package/skills/pixerate-image-editor/SKILL.md +1 -1
  121. package/skills/pixerate-paint-editor/SKILL.md +8 -5
  122. package/skills/pixerate-stickers/SKILL.md +57 -0
@@ -51,3 +51,6 @@ export type { WetBackendInfo } from '../paint/wet/world.cjs';
51
51
  export * from '../paint/gradient-paint.cjs';
52
52
  export * from './playback.cjs';
53
53
  export * from './editorDocument.cjs';
54
+ export { StickerBrowser, type StickerBrowserItem, type StickerBrowserState } from '../stickers/browser.cjs';
55
+ export type { StickerProvider, StickerRef, StickerSummary } from '../stickers/types.cjs';
56
+ export * from './sticker-art.cjs';
@@ -51,3 +51,6 @@ export type { WetBackendInfo } from '../paint/wet/world.js';
51
51
  export * from '../paint/gradient-paint.js';
52
52
  export * from './playback.js';
53
53
  export * from './editorDocument.js';
54
+ export { StickerBrowser, type StickerBrowserItem, type StickerBrowserState } from '../stickers/browser.js';
55
+ export type { StickerProvider, StickerRef, StickerSummary } from '../stickers/types.js';
56
+ export * from './sticker-art.js';
@@ -1,6 +1,10 @@
1
+ import {
2
+ StickerBrowser,
3
+ editorStickers
4
+ } from "../chunk-U4NUOKBT.js";
1
5
  import {
2
6
  toVideoFfmpeg
3
- } from "../chunk-L3JFOTBQ.js";
7
+ } from "../chunk-5E2Q7ZHI.js";
4
8
  import {
5
9
  createLayerEffectTools,
6
10
  deserializeLayers,
@@ -8,7 +12,7 @@ import {
8
12
  resolveExternalAssets,
9
13
  serializeLayers,
10
14
  serializeLayersExternal
11
- } from "../chunk-ZFSLEOSQ.js";
15
+ } from "../chunk-3TWOCSCY.js";
12
16
  import "../chunk-3CI7FRMK.js";
13
17
  import "../chunk-ZNA3IQZF.js";
14
18
  import {
@@ -26,7 +30,7 @@ import {
26
30
  mergeLayerEffect,
27
31
  newEffectId,
28
32
  validateLayerEffects
29
- } from "../chunk-UOOK7HTX.js";
33
+ } from "../chunk-3PPJRMIG.js";
30
34
  import "../chunk-OHKOFKBY.js";
31
35
  import "../chunk-ZIF4UJJ6.js";
32
36
  import {
@@ -53,7 +57,7 @@ import {
53
57
  pigmentOf,
54
58
  pointerPressure,
55
59
  wetSupport
56
- } from "../chunk-P3NIPIKS.js";
60
+ } from "../chunk-WQCNC4DK.js";
57
61
  import "../chunk-HVQVHUTV.js";
58
62
  import {
59
63
  writeZip
@@ -64,7 +68,7 @@ import {
64
68
  realPresenceClock,
65
69
  tweenPresenceCursor
66
70
  } from "../chunk-IVSWRVB4.js";
67
- import "../chunk-Q2HA52V4.js";
71
+ import "../chunk-KDLBJ6QR.js";
68
72
  import {
69
73
  BRUSH_ID,
70
74
  BRUSH_ROTATIONS,
@@ -89,6 +93,7 @@ import {
89
93
  IDENTITY_COPY,
90
94
  IMPASTO_TOOLS,
91
95
  MAX_DOT_TEXTURES,
96
+ MAX_STICKER_STAMPS,
92
97
  MULTI_COLOR_MODES,
93
98
  PAINT_BRUSH_CATEGORIES,
94
99
  PAINT_BRUSH_ENGINES,
@@ -100,7 +105,8 @@ import {
100
105
  PenDabWalker,
101
106
  PenSmoother,
102
107
  RIBBON_PAIRS,
103
- STAMP_KINDS,
108
+ STICKER_ART_SIZE,
109
+ StickerArtCache,
104
110
  StickerSpray,
105
111
  WET_MEDIA,
106
112
  WET_TOOLS,
@@ -108,6 +114,7 @@ import {
108
114
  brushTakesPaint,
109
115
  brushToJSON,
110
116
  clonePaper,
117
+ defaultStickerRasterizer,
111
118
  drawSticker,
112
119
  effectDabField,
113
120
  effectPaintKey,
@@ -138,19 +145,29 @@ import {
138
145
  readPaintEffectPaint,
139
146
  renderPaper,
140
147
  renderStickers,
148
+ sampleArt,
141
149
  sampleEffectAt,
142
150
  sampleEffectField,
143
- stampCoverage,
144
151
  stickerAt,
145
152
  stickerRect,
153
+ stickerStamp,
146
154
  stickerSurface,
147
155
  tiltToOrientation,
148
156
  toStrokePoint,
149
157
  usesPaintExchange
150
- } from "../chunk-VNBUDVD4.js";
158
+ } from "../chunk-OTEPAQJX.js";
159
+ import {
160
+ STAMP_KINDS,
161
+ StickersSlot,
162
+ createStickerTools,
163
+ editorStampOf,
164
+ normalizeStickerRef,
165
+ stampCoverage
166
+ } from "../chunk-WKH5ZAUA.js";
151
167
  import "../chunk-M6DNZNVY.js";
152
168
  import "../chunk-WEIK3UYB.js";
153
169
  import "../chunk-PWBZH3FK.js";
170
+ import "../chunk-SZTI6EER.js";
154
171
  import {
155
172
  EffectRendererPool
156
173
  } from "../chunk-EHLOCVWB.js";
@@ -159,7 +176,7 @@ import {
159
176
  EffectsSlot,
160
177
  createEffectToolProvider,
161
178
  resolveEffectValues
162
- } from "../chunk-OFH6Q67U.js";
179
+ } from "../chunk-JA57JIT5.js";
163
180
  import "../chunk-V2ZCJRDM.js";
164
181
  import {
165
182
  CoverageMap,
@@ -188,7 +205,6 @@ import {
188
205
  PaperGrain,
189
206
  SmudgeTip,
190
207
  TileMedium,
191
- TileableNoise,
192
208
  addPaintGradientStop,
193
209
  applyStrokeToTile,
194
210
  blenderDab,
@@ -198,46 +214,51 @@ import {
198
214
  exchangeRates,
199
215
  grainCatch,
200
216
  grainHeights,
201
- hash2,
202
217
  hexToPaintRgb,
203
218
  isGradientPaint,
204
219
  loadMixer,
205
- mix32,
206
220
  mixerRates,
207
221
  normalizeHexColor,
208
222
  paintGradientMappingFor,
209
223
  paintSourceColor,
210
224
  paintSourceCss,
211
225
  parsePaintSource,
212
- rand01,
213
- randSigned,
214
226
  rasterizeDab,
215
227
  readPaintSource,
216
228
  removePaintGradientStop,
217
229
  resolvePaintGradient,
218
230
  reversePaintGradient,
219
231
  scalePaintGradient,
220
- seedFromString,
221
232
  solidPaint,
222
233
  updatePaintGradientStop
223
- } from "../chunk-2PBZBRP5.js";
234
+ } from "../chunk-D5KGAO4Z.js";
235
+ import {
236
+ TileableNoise,
237
+ hash2,
238
+ mix32,
239
+ rand01,
240
+ randSigned,
241
+ seedFromString
242
+ } from "../chunk-4D6KP5BV.js";
224
243
  import "../chunk-ODBT55Q7.js";
225
244
  import {
226
245
  BLEND_MODES,
227
246
  PAINTERLY_BLEND_MODES,
247
+ isBlendMode,
248
+ isPainterlyBlendMode,
249
+ mixPigment8,
250
+ mixPigments,
251
+ standardBlendMode
252
+ } from "../chunk-IRSTHLQQ.js";
253
+ import {
228
254
  base64ToBytes,
229
255
  bytesToBase64,
230
256
  decodePng,
231
257
  encodePng,
232
- isBlendMode,
233
- isPainterlyBlendMode,
234
258
  isPng,
235
- mixPigment8,
236
- mixPigments,
237
259
  parseDataUrl,
238
- pngDataUrl,
239
- standardBlendMode
240
- } from "../chunk-42TWUPNJ.js";
260
+ pngDataUrl
261
+ } from "../chunk-OTTT5N3K.js";
241
262
  import {
242
263
  TILE,
243
264
  TiledSurface,
@@ -1305,7 +1326,7 @@ var PaintStrokeSession = class _PaintStrokeSession {
1305
1326
  };
1306
1327
  if (this.wetDriver) {
1307
1328
  } else if (init.sticker) {
1308
- this.stickerSpray = new StickerSpray({ brush, target: this.tileTarget(), color: init.colorHex, seed: init.seed, copies: this.copies, nextId: init.sticker.nextId, paint: init.paint ?? null, effect });
1329
+ this.stickerSpray = new StickerSpray({ brush, target: this.tileTarget(), color: init.colorHex, seed: init.seed, copies: this.copies, nextId: init.sticker.nextId, paint: init.paint ?? null, effect, art: init.sticker.art });
1309
1330
  } else if (init.thick) {
1310
1331
  const rgb = (c) => [c[0] / 255, c[1] / 255, c[2] / 255];
1311
1332
  this.thickDriver = new ThickStrokeDriver({ brush, target: this.tileTarget(), channels: init.thick.channels, color: rgb(init.color), load: init.mixerLoad, seed: init.seed, copies: this.copies, paint: init.paint ?? null, effect });
@@ -1515,6 +1536,7 @@ var PaintStrokeSession = class _PaintStrokeSession {
1515
1536
  const surface = changed ? new TiledSurface(ch, tiles, this.base.defaultValue) : null;
1516
1537
  const dabs = this.dry ? this.dry.dabCount : this.thickDriver ? this.thickDriver.dabCount : this.stickerSpray ? this.stickerSpray.dabCount : this.wet.dabCount;
1517
1538
  this.result = { layerId: this.layerId, bounds: changed ? this.bounds : null, dabs, strokeId: null };
1539
+ if (this.stickerSpray?.skipped.size) this.result.skippedStickers = [...this.stickerSpray.skipped];
1518
1540
  const carried = this.wet?.load ?? this.thickDriver?.load;
1519
1541
  if (carried) this.result.mixerLoad = this.init.brush.behavior.dirty ? carried : cleanMixer(carried);
1520
1542
  this.host.commit(this, surface, false);
@@ -4161,10 +4183,16 @@ var PaintEditorController = class _PaintEditorController {
4161
4183
  wetOp = null;
4162
4184
  /** The effects provider slot (see `setEffectsProvider`). */
4163
4185
  effects = new EffectsSlot();
4186
+ /** The sticker library slot (see `setStickersProvider`). */
4187
+ stickers = new StickersSlot(editorStickers());
4188
+ stickerArt = new StickerArtCache();
4189
+ rasterizeSticker;
4164
4190
  effectsRenderer = new PaintEffectsRenderer();
4165
4191
  paperEffectNodeCache = null;
4166
4192
  constructor(options = {}) {
4167
4193
  this.historyLimit = Math.max(1, options.historyLimit ?? 200);
4194
+ this.rasterizeSticker = options.rasterizeSticker ?? defaultStickerRasterizer;
4195
+ if (options.stickers) this.stickers.set(options.stickers);
4168
4196
  this.doc = createPaintDocument({ width: options.width, height: options.height, dpi: options.dpi, paper: this.resolvePaper(options.paper) });
4169
4197
  this.userBrushes = (options.brushes ?? []).map((b) => normalizePaintBrush({ ...b, builtin: false }));
4170
4198
  const start = this.findBrush(options.brushId ?? DEFAULT_BRUSH_ID) ?? this.findBrush(DEFAULT_BRUSH_ID);
@@ -5323,6 +5351,7 @@ var PaintEditorController = class _PaintEditorController {
5323
5351
  else delete next.builtin;
5324
5352
  this.brush = next;
5325
5353
  this.emit([]);
5354
+ if (next.engine === "sticker" && next.sticker.stamps.some((r) => !editorStampOf(r))) void this.prepareStickers(next.sticker.stamps).catch(() => this.emit([]));
5326
5355
  return this.brush;
5327
5356
  }
5328
5357
  /** Saves the active brush (or `brush`) into the user library under `id` / `name`. */
@@ -5648,7 +5677,7 @@ var PaintEditorController = class _PaintEditorController {
5648
5677
  thick: brush.engine === "impasto" ? { channels: doc.thick?.[layer.id] ?? emptyThickChannels() } : void 0,
5649
5678
  // Light paint: a twin of the stroke paints the light channel (laying, dimming, moving light).
5650
5679
  light: !wet && brush.engine !== "sticker" && (brush.light.amount > 0 || doc.light?.[layer.id]) ? { surface: doc.light?.[layer.id] ?? emptyLight() } : null,
5651
- sticker: brush.engine === "sticker" ? { nextId: this.nextStickerNumber(doc) } : void 0,
5680
+ sticker: brush.engine === "sticker" ? { nextId: this.nextStickerNumber(doc), art: this.stickerArt.get } : void 0,
5652
5681
  paint: effect ? null : this.strokeGradient(init, brush, color),
5653
5682
  effect
5654
5683
  });
@@ -6445,9 +6474,19 @@ var PaintEditorController = class _PaintEditorController {
6445
6474
  const stickers = {};
6446
6475
  for (const [id, list] of Object.entries(ext.stickers)) {
6447
6476
  if (!findLayer(state.layers, id) || !Array.isArray(list)) continue;
6448
- const ok = list.filter((x) => x && typeof x.id === "string" && STAMP_KINDS.includes(x.stamp) && Number.isFinite(x.x) && Number.isFinite(x.y) && x.size > 0);
6477
+ const ok = list.flatMap((x) => {
6478
+ if (!x || typeof x.id !== "string" || !Number.isFinite(x.x) || !Number.isFinite(x.y) || !(x.size > 0)) return [];
6479
+ try {
6480
+ const ref2 = normalizeStickerRef(x.ref ?? x.stamp);
6481
+ const stamp = editorStampOf(ref2);
6482
+ const { stamp: _old, ...rest } = x;
6483
+ return [{ ...rest, ref: ref2, ...stamp ? { stamp } : {} }];
6484
+ } catch {
6485
+ return [];
6486
+ }
6487
+ });
6449
6488
  if (ok.length !== list.length) problems.push(`Some stickers of layer "${id}" could not be read; they were dropped.`);
6450
- stickers[id] = ok.map((x) => ({ ...x }));
6489
+ stickers[id] = ok;
6451
6490
  }
6452
6491
  if (Object.keys(stickers).length) state = { ...state, stickers };
6453
6492
  }
@@ -6551,6 +6590,8 @@ var PaintEditorController = class _PaintEditorController {
6551
6590
  delete this.extensions.paperEffect;
6552
6591
  this.viewCompositor.clear();
6553
6592
  this.emit();
6593
+ const refs = Object.values(this.doc.stickers ?? {}).flatMap((list) => list.map((x) => x.ref));
6594
+ if (refs.some((r) => !editorStampOf(r))) void this.prepareStickers(refs).catch(() => this.emit([]));
6554
6595
  return loaded.problems;
6555
6596
  }
6556
6597
  /** Opens a saved document (clears the history). Returns what could not be read. */
@@ -6878,6 +6919,56 @@ var PaintEditorController = class _PaintEditorController {
6878
6919
  if (!stickers) throw new PaintEditorError(`Layer "${l.name}" has no stickers; spray some with a sticker brush (list_brushes category sticker).`);
6879
6920
  return { layer: l, stickers };
6880
6921
  }
6922
+ // --- The sticker library ---------------------------------------------------------
6923
+ /** The sticker library: the editor's own stamps unless a host set its own. */
6924
+ get stickersProvider() {
6925
+ return this.stickers.provider;
6926
+ }
6927
+ /**
6928
+ * Sets the sticker library (`null` goes back to the editor's own stamps, `editorStickers()`);
6929
+ * to offer both, pass `combineStickerProviders([editorStickers(), yours])`. Loaded art is
6930
+ * forgotten. Not an edit: no undo step.
6931
+ */
6932
+ setStickersProvider(provider) {
6933
+ if ((provider ?? this.stickers.fallback) === this.stickers.provider) return;
6934
+ this.stickers.set(provider);
6935
+ this.stickerArt.clear();
6936
+ this.emit([]);
6937
+ }
6938
+ /**
6939
+ * Loads the art of `refs` (provider stickers; editor stamps need none) so sprays and placements
6940
+ * can draw them. Rejects with a `PaintEditorError` naming an unknown ref and the closest known
6941
+ * ones, or a sticker whose art failed. Emits when art arrives, so views redraw.
6942
+ */
6943
+ async prepareStickers(refs) {
6944
+ const list = [...new Set(refs.map((r) => this.readStickerRef(r)))].filter((r) => !editorStampOf(r));
6945
+ try {
6946
+ await Promise.all(list.map((r) => this.stickerArt.ensure(this.stickers.provider, r, this.rasterizeSticker)));
6947
+ } catch (e) {
6948
+ throw new PaintEditorError(e instanceof Error ? e.message : String(e));
6949
+ } finally {
6950
+ if (list.length) this.emit([]);
6951
+ }
6952
+ }
6953
+ /** Whether a sticker's art is ready to draw: `ready` (always for editor stamps), `loading`, `failed` (with why) or `none`. */
6954
+ stickerArtStatus(ref2) {
6955
+ return this.stickerArt.status(this.readStickerRef(ref2));
6956
+ }
6957
+ readStickerRef(ref2) {
6958
+ try {
6959
+ return normalizeStickerRef(ref2);
6960
+ } catch (e) {
6961
+ throw new PaintEditorError(e.message);
6962
+ }
6963
+ }
6964
+ /** Refuses to redraw stickers whose art has not loaded (they would vanish), naming them and what to call. */
6965
+ requireStickerArt(stickers) {
6966
+ const missing = [...new Set(stickers.filter((s) => !stickerStamp(s) && !this.stickerArt.get(s.ref)).map((s) => s.ref))];
6967
+ if (missing.length) {
6968
+ for (const r of missing) void this.stickerArt.ensure(this.stickers.provider, r, this.rasterizeSticker).then(() => this.emit([]), () => this.emit([]));
6969
+ throw new PaintEditorError(`The art for ${missing.map((r) => `"${r}"`).join(", ")} has not loaded yet; it is loading now (prepareStickers), so try again when it has.`);
6970
+ }
6971
+ }
6881
6972
  /** A layer's stickers, bottom first. */
6882
6973
  listStickers(layerId) {
6883
6974
  const id = layerId ?? this.doc.activeLayerId;
@@ -6891,6 +6982,7 @@ var PaintEditorController = class _PaintEditorController {
6891
6982
  */
6892
6983
  commitStickers(label, layer, stickers, dirty) {
6893
6984
  if (isLayerLocked(layer, "pixels")) throw new PaintEditorError(`Layer "${layer.name}" has its pixels locked; unlock it first.`);
6985
+ this.requireStickerArt(stickers);
6894
6986
  const before = this.previewBase() ?? this.doc;
6895
6987
  this.stickerPreview = null;
6896
6988
  const surface = this.redrawStickers(layer, stickers, dirty);
@@ -6899,7 +6991,7 @@ var PaintEditorController = class _PaintEditorController {
6899
6991
  }
6900
6992
  redrawStickers(layer, stickers, dirty) {
6901
6993
  const partial = dirty && !layer.offset.x && !layer.offset.y;
6902
- return partial ? stickerSurface(stickers, layer.surface, dirty) : stickerSurface(stickers);
6994
+ return partial ? stickerSurface(stickers, layer.surface, dirty, this.stickerArt.get) : stickerSurface(stickers, void 0, void 0, this.stickerArt.get);
6903
6995
  }
6904
6996
  /** The document from before the sticker preview on screen, or `null` when none is (anything else changed the document since). */
6905
6997
  previewBase() {
@@ -6918,7 +7010,7 @@ var PaintEditorController = class _PaintEditorController {
6918
7010
  const id = layerId ?? this.doc.activeLayerId;
6919
7011
  if (!id) return null;
6920
7012
  this.requireLayer(id);
6921
- const hit = stickerAt(this.doc.stickers?.[id] ?? [], x, y);
7013
+ const hit = stickerAt(this.doc.stickers?.[id] ?? [], x, y, this.stickerArt.get);
6922
7014
  return hit ? { ...hit } : null;
6923
7015
  }
6924
7016
  /** Picks a sticker for the panel and canvas (`null` for none). Editor state, not an undo step. */
@@ -6972,7 +7064,7 @@ var PaintEditorController = class _PaintEditorController {
6972
7064
  */
6973
7065
  addStickers(layerId, input) {
6974
7066
  const layer = this.wetLayer(layerId, "add stickers to");
6975
- if (!input.length) throw new PaintEditorError("Pass at least one sticker (stamp, x, y).");
7067
+ if (!input.length) throw new PaintEditorError("Pass at least one sticker (ref, x, y).");
6976
7068
  if (input.length > MAX_ADD_STICKERS) throw new PaintEditorError(`At most ${MAX_ADD_STICKERS} stickers per call; split them over several calls.`);
6977
7069
  const existing = this.doc.stickers?.[layer.id];
6978
7070
  if (!existing?.length) {
@@ -6980,7 +7072,8 @@ var PaintEditorController = class _PaintEditorController {
6980
7072
  }
6981
7073
  let n = this.nextStickerNumber();
6982
7074
  const added = input.map((raw, i) => {
6983
- for (const k of ["stamp", "x", "y"]) if (raw[k] === void 0) throw new PaintEditorError(`Sticker ${i} needs ${k}.`);
7075
+ if (raw.ref === void 0 && raw.stamp === void 0) throw new PaintEditorError(`Sticker ${i} needs ref (a sticker ref from find_stickers, e.g. "editor:star").`);
7076
+ for (const k of ["x", "y"]) if (raw[k] === void 0) throw new PaintEditorError(`Sticker ${i} needs ${k}.`);
6984
7077
  let u;
6985
7078
  try {
6986
7079
  u = this.readStickerUpdate(raw);
@@ -8045,7 +8138,7 @@ function createPaintStickerTools(c) {
8045
8138
  {
8046
8139
  name: "list_stickers",
8047
8140
  title: "List stickers",
8048
- description: "Lists a layer\u2019s stickers bottom first: id, stamp, x, y (centre, document pixels), size (diameter px), rotation (degrees clockwise), color, opacity. Empty for a layer without stickers. Changes nothing.",
8141
+ description: "Lists a layer\u2019s stickers bottom first: id, ref (provider:id; stamp too for the editor\u2019s own), x, y (centre, document pixels), size (diameter px), rotation (degrees clockwise), color, opacity. Empty for a layer without stickers. Changes nothing.",
8049
8142
  inputSchema: { type: "object", properties: { layerId: LAYER_ID }, additionalProperties: false },
8050
8143
  annotations: { title: "List stickers", ...READ },
8051
8144
  coordinates: { out: ["stickers[]"] },
@@ -8072,7 +8165,7 @@ function createPaintStickerTools(c) {
8072
8165
  {
8073
8166
  name: "add_stickers",
8074
8167
  title: "Place stickers",
8075
- description: "Places stickers exactly where you say, on top of a sticker layer or onto an empty layer (which becomes a sticker layer). Use it for deliberate placement; spray with paint_stroke and a sticker brush for a random scatter. One undo step. Returns the new stickers with their ids, for update_sticker, arrange_stickers and remove_stickers.",
8168
+ description: "Places stickers exactly where you say, on top of a sticker layer or onto an empty layer (which becomes a sticker layer): any sticker from the sticker library by ref (find_stickers), its art loaded first; tintable ones take color. Use it for deliberate placement; spray with paint_stroke and a sticker brush for a random scatter. An unknown ref is refused with the closest ones. One undo step. Returns the new stickers with their ids, for update_sticker, arrange_stickers and remove_stickers.",
8076
8169
  inputSchema: {
8077
8170
  type: "object",
8078
8171
  properties: {
@@ -8085,7 +8178,8 @@ function createPaintStickerTools(c) {
8085
8178
  items: {
8086
8179
  type: "object",
8087
8180
  properties: {
8088
- stamp: { type: "string", enum: [...STAMP_KINDS], description: "The stamp." },
8181
+ ref: { type: "string", minLength: 1, description: "The sticker: a ref provider:id from find_stickers (e.g. editor:star). Give ref or stamp." },
8182
+ stamp: { type: "string", enum: [...STAMP_KINDS], description: "Older form: an editor stamp (same as ref editor:<stamp>)." },
8089
8183
  x: { type: "number", description: "Centre x in document pixels." },
8090
8184
  y: { type: "number", description: "Centre y in document pixels." },
8091
8185
  size: { type: "number", minimum: 2, maximum: 2048, description: "Diameter in pixels (default 48)." },
@@ -8094,7 +8188,7 @@ function createPaintStickerTools(c) {
8094
8188
  opacity: { type: "number", minimum: 0, maximum: 1, description: "Opacity 0..1 (default 1)." },
8095
8189
  seed: { type: "integer", minimum: 0, description: "Texture seed (default from the new id); splat and confetti shapes vary with it." }
8096
8190
  },
8097
- required: ["stamp", "x", "y"],
8191
+ required: ["x", "y"],
8098
8192
  additionalProperties: false
8099
8193
  }
8100
8194
  }
@@ -8104,7 +8198,14 @@ function createPaintStickerTools(c) {
8104
8198
  },
8105
8199
  annotations: { title: "Place stickers", ...WRITE },
8106
8200
  coordinates: { in: ["stickers[]"], out: ["stickers[]"] },
8107
- handler: ({ layerId, stickers }) => ({ layerId: layerId ?? c.document.activeLayerId, stickers: c.addStickers(layerId, stickers) })
8201
+ handler: async ({ layerId, stickers }) => {
8202
+ const list = stickers;
8203
+ list.forEach((x, i) => {
8204
+ if (x.ref === void 0 && x.stamp === void 0) throw new Error(`Sticker ${i} needs ref (a sticker ref from find_stickers, e.g. "editor:star").`);
8205
+ });
8206
+ await c.prepareStickers(list.map((x) => x.ref ?? `editor:${x.stamp}`));
8207
+ return { layerId: layerId ?? c.document.activeLayerId, stickers: c.addStickers(layerId, list) };
8208
+ }
8108
8209
  },
8109
8210
  {
8110
8211
  name: "update_sticker",
@@ -8115,7 +8216,8 @@ function createPaintStickerTools(c) {
8115
8216
  properties: {
8116
8217
  layerId: LAYER_ID,
8117
8218
  id: { type: "string", description: "Sticker id from list_stickers." },
8118
- stamp: { type: "string", enum: [...STAMP_KINDS], description: "Another stamp." },
8219
+ ref: { type: "string", minLength: 1, description: "Another sticker: a ref provider:id from find_stickers." },
8220
+ stamp: { type: "string", enum: [...STAMP_KINDS], description: "Older form: another editor stamp (same as ref editor:<stamp>)." },
8119
8221
  x: { type: "number", description: "Centre x in document pixels." },
8120
8222
  y: { type: "number", description: "Centre y in document pixels." },
8121
8223
  size: { type: "number", minimum: 2, maximum: 2048, description: "Diameter in pixels." },
@@ -8128,7 +8230,11 @@ function createPaintStickerTools(c) {
8128
8230
  },
8129
8231
  annotations: { title: "Change a sticker", ...WRITE },
8130
8232
  coordinates: { in: [""], out: [""] },
8131
- handler: ({ layerId, id, ...update }) => c.updateSticker(layerId, id, update)
8233
+ handler: async ({ layerId, id, ...update }) => {
8234
+ const refs = c.listStickers(layerId).map((s) => s.ref);
8235
+ await c.prepareStickers(update.ref ? [...refs, update.ref] : refs);
8236
+ return c.updateSticker(layerId, id, update);
8237
+ }
8132
8238
  },
8133
8239
  {
8134
8240
  name: "arrange_stickers",
@@ -8145,7 +8251,10 @@ function createPaintStickerTools(c) {
8145
8251
  additionalProperties: false
8146
8252
  },
8147
8253
  annotations: { title: "Bring stickers forward or back", ...WRITE },
8148
- handler: ({ layerId, ids, to }) => ({ order: c.arrangeStickers(layerId, ids, to) })
8254
+ handler: async ({ layerId, ids, to }) => {
8255
+ await c.prepareStickers(c.listStickers(layerId).map((s) => s.ref));
8256
+ return { order: c.arrangeStickers(layerId, ids, to) };
8257
+ }
8149
8258
  },
8150
8259
  {
8151
8260
  name: "remove_stickers",
@@ -8153,7 +8262,10 @@ function createPaintStickerTools(c) {
8153
8262
  description: "Deletes stickers by id, or every sticker on the layer when ids is missing. One undo step. Returns the ids removed.",
8154
8263
  inputSchema: { type: "object", properties: { layerId: LAYER_ID, ids: { type: "array", items: { type: "string", description: "Sticker id." }, description: "Sticker ids (default all)." } }, additionalProperties: false },
8155
8264
  annotations: { title: "Delete stickers", ...DESTRUCTIVE },
8156
- handler: ({ layerId, ids }) => ({ removed: c.removeStickers(layerId, ids) })
8265
+ handler: async ({ layerId, ids }) => {
8266
+ await c.prepareStickers(c.listStickers(layerId).map((s) => s.ref));
8267
+ return { removed: c.removeStickers(layerId, ids) };
8268
+ }
8157
8269
  }
8158
8270
  ];
8159
8271
  }
@@ -9167,7 +9279,13 @@ var STICKER_BRUSH = {
9167
9279
  type: "object",
9168
9280
  description: "Sticker engine settings: stamps sprayed along the stroke as editable stickers. Missing fields keep their current values.",
9169
9281
  properties: {
9170
- stamps: { type: "array", minItems: 1, maxItems: 9, items: { type: "string", enum: [...STAMP_KINDS], description: "A stamp." }, description: "The stamps to spray (one picked at random per sticker)." },
9282
+ stamps: {
9283
+ type: "array",
9284
+ minItems: 1,
9285
+ maxItems: MAX_STICKER_STAMPS,
9286
+ items: { type: "string", minLength: 1, description: "A sticker ref provider:id from find_stickers (e.g. editor:star); a bare editor stamp (star) means editor:star." },
9287
+ description: `The stickers to spray, one picked at random per sticker: refs from find_stickers (the editor's own: ${STAMP_KINDS.map((k) => `editor:${k}`).join(", ")}). Each is checked against the sticker library and an unknown ref is refused with the closest ones. A provider's sticker is drawn from its art (tinted to the paint colour when tintable), loaded before the stroke.`
9288
+ },
9171
9289
  density: { type: "number", minimum: 0, maximum: 1, description: "How closely stickers follow each other: about density \xD7 4 stickers per tip diameter of travel (0.25 \u2248 one per diameter, 1 \u2248 four). Default 0.4." },
9172
9290
  sizeJitter: { type: "number", minimum: 0, maximum: 1, description: "Random size change." },
9173
9291
  rotationJitter: { type: "number", minimum: 0, maximum: 1, description: "Random turn as a fraction of \xB1180\xB0." },
@@ -9594,7 +9712,11 @@ function createPaintEditorToolProvider(controller, options = {}) {
9594
9712
  description: "Chooses the active brush (id) and / or changes its settings; strokes without a brush use it. Editor state, not an undo step. Changes stay on the active brush until save_brush stores them. Returns the active brush.",
9595
9713
  inputSchema: { type: "object", properties: { id: { type: "string", description: "Brush id from list_brushes to start from." }, ...BRUSH_FIELDS }, additionalProperties: false },
9596
9714
  annotations: { title: "Set the brush", ...SET4 },
9597
- handler: (a) => brushToJSON(c.setBrush(a))
9715
+ handler: async (a) => {
9716
+ const stamps = a.sticker?.stamps;
9717
+ if (stamps) await c.prepareStickers(stamps);
9718
+ return brushToJSON(c.setBrush(a));
9719
+ }
9598
9720
  });
9599
9721
  add({
9600
9722
  name: "save_brush",
@@ -9770,6 +9892,9 @@ function createPaintEditorToolProvider(controller, options = {}) {
9770
9892
  coordinates: { in: ["points[]"], out: ["bounds"] },
9771
9893
  handler: async (a) => {
9772
9894
  await c.wetIdle();
9895
+ const base = a.brushId ? c.getBrush(a.brushId) : c.getState().brush;
9896
+ const over = a.brush;
9897
+ if ((over?.engine ?? base?.engine) === "sticker") await c.prepareStickers(over?.sticker?.stamps ?? base?.sticker.stamps ?? []);
9773
9898
  const stroke = { points: a.points, layerId: a.layerId, brushId: a.brushId, brush: a.brush, color: a.color, paint: a.paint, seed: a.seed, snapToPerspective: a.snapToPerspective };
9774
9899
  const r = await act({ kind: "stroke", stroke }, () => c.paintStroke(stroke));
9775
9900
  return r.mixerLoad ? { ...r, mixerLoad: loadResult(r.mixerLoad) } : r;
@@ -10078,6 +10203,7 @@ function createPaintEditorToolProvider(controller, options = {}) {
10078
10203
  tools.push(...createPaintReplayTools(c));
10079
10204
  tools.push(...createPaintStickerTools(c));
10080
10205
  tools.push(...createPigmentTools());
10206
+ tools.push(...createStickerTools({ provider: () => c.stickersProvider }));
10081
10207
  tools.push(
10082
10208
  ...createLayerEffectTools(
10083
10209
  {
@@ -10251,7 +10377,7 @@ var PaintGesture = class {
10251
10377
  }
10252
10378
  const brush = this.controller.getState().brush;
10253
10379
  const size = Math.min(2048, Math.max(2, Math.round(brush.tip.size)));
10254
- const [added] = this.controller.addStickers(void 0, [{ stamp: brush.sticker.stamps[0] ?? "star", x: round2(p.x), y: round2(p.y), size }]);
10380
+ const [added] = this.controller.addStickers(void 0, [{ ref: brush.sticker.stamps[0] ?? "editor:star", x: round2(p.x), y: round2(p.y), size }]);
10255
10381
  this.controller.selectSticker(added.id);
10256
10382
  } catch (err) {
10257
10383
  this.error = err instanceof Error ? err.message : String(err);
@@ -10787,6 +10913,15 @@ var RIBBON_PAIR_LABELS = { adjacent: "Neighbours", "first-last": "Outermost" };
10787
10913
  var DOT_TEXTURE_ORDER_LABELS = { sequence: "In turn", random: "Random" };
10788
10914
  var DOT_ROTATION_LABELS = { follow: "Follow motion", random: "Random", fixed: "Tip angle" };
10789
10915
  var STAMP_LABELS = { dot: "Dot", star: "Star", heart: "Heart", leaf: "Leaf", flower: "Flower", confetti: "Confetti", splat: "Splat", sparkle: "Sparkle", ring: "Ring" };
10916
+ function toggleStickerRef(refs, ref2) {
10917
+ if (refs.includes(ref2)) return refs.length > 1 ? refs.filter((r) => r !== ref2) : [...refs];
10918
+ return refs.length < MAX_STICKER_STAMPS ? [...refs, ref2] : [...refs];
10919
+ }
10920
+ function stickerRefLabel(ref2) {
10921
+ const stamp = ref2.startsWith("editor:") ? ref2.slice(7) : null;
10922
+ if (stamp && STAMP_LABELS[stamp]) return STAMP_LABELS[stamp];
10923
+ return ref2.slice(ref2.indexOf(":") + 1);
10924
+ }
10790
10925
  function toggleStamp(stamps, stamp) {
10791
10926
  const next = stamps.includes(stamp) ? stamps.filter((s) => s !== stamp) : [...stamps, stamp];
10792
10927
  return next.length ? next : [stamp];
@@ -11141,6 +11276,7 @@ export {
11141
11276
  MAX_DOT_TEXTURES,
11142
11277
  MAX_IMAGE_SIDE,
11143
11278
  MAX_LIVE_EFFECT_SOURCES,
11279
+ MAX_STICKER_STAMPS,
11144
11280
  MAX_ZOOM,
11145
11281
  MIN_CANVAS_SIDE,
11146
11282
  MIN_ZOOM,
@@ -11205,10 +11341,13 @@ export {
11205
11341
  STAMP_LABELS,
11206
11342
  STENCIL_KINDS,
11207
11343
  STENCIL_SHAPES,
11344
+ STICKER_ART_SIZE,
11208
11345
  STICKER_SLIDERS,
11209
11346
  STROKE_SLIDERS,
11210
11347
  SYMMETRY_MODES,
11211
11348
  StencilSnapper,
11349
+ StickerArtCache,
11350
+ StickerBrowser,
11212
11351
  StickerSpray,
11213
11352
  TRACING_NODE_ID,
11214
11353
  ThickStrokeDriver,
@@ -11256,6 +11395,7 @@ export {
11256
11395
  decodeImageBlob,
11257
11396
  defaultGuides,
11258
11397
  defaultImageEncoder,
11398
+ defaultStickerRasterizer,
11259
11399
  deserializePaintDocument,
11260
11400
  deserializePaintDocumentAsync,
11261
11401
  documentExtensions,
@@ -11374,6 +11514,7 @@ export {
11374
11514
  rgbToHexColor,
11375
11515
  rgbToHsl,
11376
11516
  rgbToHsv,
11517
+ sampleArt,
11377
11518
  sampleEffectAt,
11378
11519
  sampleEffectField,
11379
11520
  samplePressure,
@@ -11391,6 +11532,8 @@ export {
11391
11532
  stencilOutline,
11392
11533
  stickerAt,
11393
11534
  stickerRect,
11535
+ stickerRefLabel,
11536
+ stickerStamp,
11394
11537
  stickerSurface,
11395
11538
  strokeBounds,
11396
11539
  strokeDuration,
@@ -11408,6 +11551,7 @@ export {
11408
11551
  toStrokePoint,
11409
11552
  toggleDotTexture,
11410
11553
  toggleStamp,
11554
+ toggleStickerRef,
11411
11555
  translateStencil,
11412
11556
  updatePaintGradientStop,
11413
11557
  usesPaintExchange,
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Art for stickers from a sticker provider (anything but the editor's own procedural stamps): the
3
+ * spray brush draws while a stroke is in progress, so it can't wait for a provider. Each sticker
4
+ * is loaded once, rasterised to RGBA and kept here; drawing reads it synchronously.
5
+ *
6
+ * PNG art (`data:` URLs) is decoded here, in any environment. SVG and `https:` images need a
7
+ * rasteriser: the browser's (`createImageBitmap` and `OffscreenCanvas`) by default, or the
8
+ * host's (`PaintEditorOptions.rasterizeSticker`).
9
+ */
10
+ import type { StickerAsset, StickerProvider, StickerRef } from '../stickers/types.cjs';
11
+ /** Rasterised sticker art (straight RGBA) and whether to recolour it. */
12
+ export interface StickerArt {
13
+ width: number;
14
+ height: number;
15
+ data: Uint8ClampedArray;
16
+ /** Flat art: drawn in the sticker's colour, keeping its alpha. */
17
+ tintable: boolean;
18
+ }
19
+ /** The art for a ref, when it has loaded. */
20
+ export type StickerArtLookup = (ref: StickerRef) => StickerArt | undefined;
21
+ /** Turns a sticker asset into RGBA at about `size` px on its longest side. */
22
+ export type StickerRasterizer = (asset: StickerAsset, size: number) => Promise<{
23
+ width: number;
24
+ height: number;
25
+ data: Uint8ClampedArray;
26
+ }>;
27
+ /** Longest side sticker art is kept at (px); larger stickers are drawn from it, smoothly scaled. */
28
+ export declare const STICKER_ART_SIZE = 256;
29
+ /**
30
+ * Decodes PNG data URLs anywhere; draws SVG and other images with the browser's
31
+ * `createImageBitmap` and `OffscreenCanvas` when present, and otherwise refuses, naming the option
32
+ * that adds a rasteriser.
33
+ */
34
+ export declare const defaultStickerRasterizer: StickerRasterizer;
35
+ /** Loaded sticker art by ref, with the state of each load. */
36
+ export declare class StickerArtCache {
37
+ private readonly entries;
38
+ /** The art for `ref` when it has loaded (editor stamps never need any). */
39
+ get: StickerArtLookup;
40
+ /** `ready`, `loading`, `failed` (with the reason) or `none` (never asked for). Editor stamps are always `ready`. */
41
+ status(ref: StickerRef): {
42
+ status: 'ready' | 'loading' | 'failed' | 'none';
43
+ error?: string;
44
+ };
45
+ /**
46
+ * Loads and rasterises `ref` from `provider` once (later calls share the load). Unknown refs
47
+ * reject with the closest known ones; failures are kept so they are reported, and retried on
48
+ * the next call.
49
+ */
50
+ ensure(provider: StickerProvider, ref: StickerRef, rasterize: StickerRasterizer): Promise<StickerArt | null>;
51
+ /** Forgets every load (a new provider). */
52
+ clear(): void;
53
+ }
54
+ /** Bilinear RGBA sample of `art` at (x, y) in its pixels (straight alpha, colour weighted by alpha). */
55
+ export declare function sampleArt(art: StickerArt, x: number, y: number, out: number[]): number[];