@amigo-labs/pincel-wasm 1.5.0 → 1.7.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/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@amigo-labs/pincel-wasm",
3
3
  "type": "module",
4
4
  "description": "WebAssembly bindings for the Pincel core (wasm-bindgen / wasm-pack target)",
5
- "version": "1.5.0",
5
+ "version": "1.7.0",
6
6
  "license": "MIT OR Apache-2.0",
7
7
  "repository": {
8
8
  "type": "git",
package/pincel_wasm.d.ts CHANGED
@@ -222,9 +222,10 @@ export class Document {
222
222
  * stable across runs and monotonic. Returns the assigned id.
223
223
  *
224
224
  * Routes through the [`AddTileset`] command so the operation joins
225
- * the undo / redo bus. Tile-image content starts empty (Aseprite
226
- * convention: tile id `0` is the implicit empty tile); per-tile
227
- * edits land alongside the Tileset Editor in M8.7.
225
+ * the undo / redo bus. The tileset starts with one stored, fully
226
+ * transparent tile `0` (Aseprite's empty tile), so the first
227
+ * [`Document::add_tile`] returns id `1` and no user tile is written
228
+ * as the empty tile (docs/specs/tilemaps.md, Decisions 2026-10-29).
228
229
  *
229
230
  * Errors when `tile_w` or `tile_h` is zero, when the existing id
230
231
  * space is exhausted (an existing tileset already uses `u32::MAX`),
@@ -291,6 +292,22 @@ export class Document {
291
292
  * The emitted `dirty-rect` event covers the bbox in sprite space.
292
293
  */
293
294
  applyEllipse(x0: number, y0: number, x1: number, y1: number, color: number, fill: boolean): void;
295
+ /**
296
+ * Fill the selection — or, without one, the active layer's cel on the
297
+ * current frame — with a dithered ramp from `foreground` at the drag
298
+ * start to `background` at the drag end, as one undo entry.
299
+ *
300
+ * - `line`: `[x0, y0, x1, y1]`, the drag's start and end sprite pixels.
301
+ * - `kind`: `linear` or `radial`.
302
+ * - `dither`: the Bayer matrix size `2`, `4` or `8`, or `0` for two
303
+ * hard bands split halfway.
304
+ * - `foreground` / `background`: `0xRRGGBBAA`.
305
+ *
306
+ * Returns `false` — and changes nothing — for a zero-length drag.
307
+ * Errors (and changes nothing) on a locked layer, a document without a
308
+ * paintable image layer, and an indexed or grayscale sprite.
309
+ */
310
+ applyGradient(line: Int32Array, kind: string, dither: number, foreground: number, background: number): boolean;
294
311
  /**
295
312
  * Rasterize a 1-pixel-wide Bresenham line between sprite-space
296
313
  * `(x0, y0)` and `(x1, y1)` with the given non-premultiplied RGBA
@@ -395,6 +412,23 @@ export class Document {
395
412
  * lands when more tools ship.
396
413
  */
397
414
  applyTool(tool_id: string, x: number, y: number, color: number): void;
415
+ /**
416
+ * Start a Pencil gesture with the Shading ink: every pixel the stroke
417
+ * touches whose color before the stroke is exactly entry `i` of `ramp`
418
+ * becomes entry `i + step`, clamped to the ramp; other colors stay.
419
+ * Each pixel changes at most once per gesture. Continue it with
420
+ * [`Self::stroke_to`] and close it with `endStroke` like any stroke.
421
+ *
422
+ * - `ramp`: the colors in palette order (`0xRRGGBBAA`), at least one.
423
+ * - `step`: `1` (left button, toward the end) or `-1` (right button,
424
+ * toward the start).
425
+ * - `size`, `shape`, `pixel_perfect`: as in [`Self::begin_stroke`].
426
+ *
427
+ * Errors (and starts nothing) for an empty ramp, another step, an
428
+ * unknown shape, a locked target layer, or a document without a
429
+ * paintable image layer.
430
+ */
431
+ beginShadingStroke(ramp: Uint32Array, step: number, size: number, shape: string, pixel_perfect: boolean): void;
398
432
  /**
399
433
  * Start a Pencil / Eraser gesture on the active layer / current frame.
400
434
  * Nothing is painted until the first [`Self::stroke_to`].
@@ -446,6 +480,14 @@ export class Document {
446
480
  * event's `(x, y, width, height)` directly.
447
481
  */
448
482
  composeDirty(frame: number, zoom: number, dx: number, dy: number, dw: number, dh: number): ComposeFrame;
483
+ /**
484
+ * [`Document::compose`] with the onion skin chosen per call: `onion =
485
+ * true` applies the configured onion skin (the same bytes as
486
+ * `compose`), `onion = false` leaves it out whatever
487
+ * [`Document::set_onion_skin`] says — for an animation preview that
488
+ * must never show ghosts (docs/specs/animation-preview.md).
489
+ */
490
+ composeFrame(frame: number, zoom: number, onion: boolean): ComposeFrame;
449
491
  /**
450
492
  * Shrink the selection by `radius` pixels (may clear it).
451
493
  */
@@ -529,7 +571,7 @@ export class Document {
529
571
  * a fresh `Uint8Array` copy. Errors surface the `pincel-core`
530
572
  * message: an unknown format or tag, a scale outside 1–10, an output
531
573
  * edge above 16384 px, a frameless sequence, or a sprite the renderer
532
- * refuses (an indexed sprite).
574
+ * refuses (a corrupt cel or a broken linked cel).
533
575
  */
534
576
  exportAnimation(format: string, tag: string | null | undefined, scale: number, loops: number): Uint8Array;
535
577
  /**
@@ -549,12 +591,29 @@ export class Document {
549
591
  * `meta.image` names `image_name` (default `"sheet.png"`). Errors
550
592
  * surface the underlying `pincel-core` message: zero columns, an
551
593
  * unknown tag, a frameless sprite, or anything the renderer refuses.
594
+ *
595
+ * `scale` (optional, default 1) upscales the sheet by an integer
596
+ * factor 1–10 with nearest-neighbour; the manifest and the `--data`
597
+ * JSON describe the scaled sheet (`meta.scale` stays `"1"`, as
598
+ * Aseprite's `--scale`). A scale outside 1–10 or a sheet edge above
599
+ * 16384 px is an error naming the limit (docs/specs/scaled-export.md).
552
600
  */
553
- exportAtlas(columns: number, tag?: string | null, image_name?: string | null): AtlasExport;
601
+ exportAtlas(columns: number, tag?: string | null, image_name?: string | null, scale?: number | null): AtlasExport;
554
602
  /**
555
603
  * The palette as a GIMP `.gpl` file called `name` (alpha dropped).
604
+ *
605
+ * Deprecated: use [`Document::export_palette`] (`exportPalette`) with
606
+ * format `gpl`. Kept for the public npm API (spec §17.5).
556
607
  */
557
608
  exportGpl(name: string): string;
609
+ /**
610
+ * The palette as a file: `format` is `gpl` (a GIMP palette called
611
+ * `name`), `hex` (Lospec), `pal` (JASC) or `png` (a one-row strip of
612
+ * `cell` × `cell` px swatches). `name` is used only by `gpl`, `cell`
613
+ * only by `png`. Errors for an unknown format, or a PNG strip of an
614
+ * empty palette or with `cell` 0.
615
+ */
616
+ exportPalette(format: string, name: string, cell: number): Uint8Array;
558
617
  /**
559
618
  * Encode one frame as an RGBA8 PNG.
560
619
  *
@@ -567,8 +626,13 @@ export class Document {
567
626
  * `pincel-core` message: an out-of-range frame, or a sprite the
568
627
  * renderer refuses (non-RGBA color mode, non-`Normal` blend mode,
569
628
  * group layer, linked cel).
629
+ *
630
+ * `scale` (optional, default 1) upscales the PNG by an integer factor
631
+ * 1–10 with nearest-neighbour (docs/specs/scaled-export.md); scale 1
632
+ * and no scale give the same bytes. A scale outside 1–10 or an output
633
+ * edge above 16384 px is an error naming the limit.
570
634
  */
571
- exportPng(frame: number): Uint8Array;
635
+ exportPng(frame: number, scale?: number | null): Uint8Array;
572
636
  /**
573
637
  * Flatten every visible layer into one image layer (hidden layers are
574
638
  * dropped) and return the new layer's id, which also becomes the
@@ -589,8 +653,21 @@ export class Document {
589
653
  /**
590
654
  * Replace the palette with a GIMP `.gpl` file's colours and return
591
655
  * how many it holds. One undo entry. Refused for indexed documents.
656
+ *
657
+ * Deprecated: use [`Document::import_palette`] (`importPalette`),
658
+ * which reads `.gpl` and the other palette formats. Kept for the
659
+ * public npm API (spec §17.5).
592
660
  */
593
661
  importGpl(text: string): number;
662
+ /**
663
+ * Replace the palette with a palette file's colours and return how
664
+ * many it holds. The format — GIMP `.gpl`, Lospec `.hex`, JASC `.pal`
665
+ * or a PNG palette image — is detected from the content, not the file
666
+ * name (spec §3.7). One undo entry. Refused for indexed documents, for
667
+ * files without colours and above 256 colours; the palette is then
668
+ * unchanged.
669
+ */
670
+ importPalette(bytes: Uint8Array): number;
594
671
  /**
595
672
  * Decode PNG bytes and add them as a new image layer named `name` on
596
673
  * top of the stack, at the current frame, anchored at the canvas
@@ -938,6 +1015,13 @@ export class Document {
938
1015
  * merge into one undo entry until [`Document::end_stroke`] seals it.
939
1016
  */
940
1017
  setFrameDuration(frame: number, duration_ms: number): void;
1018
+ /**
1019
+ * Set the grid's offset (`x`, `y`) and cell size (`width` ×
1020
+ * `height`) as one undo entry; saved in the `.aseprite` header.
1021
+ * Errors, leaving the grid unchanged, for a cell size outside
1022
+ * 1–65535 or an offset outside −32768–32767.
1023
+ */
1024
+ setGrid(x: number, y: number, width: number, height: number): void;
941
1025
  /**
942
1026
  * Set the named layer's blend mode by name (see [`blend_mode_names`]),
943
1027
  * routed through the undo bus. Emits `dirty-canvas`. Errors on an
@@ -1014,6 +1098,28 @@ export class Document {
1014
1098
  * rejects the write.
1015
1099
  */
1016
1100
  setSliceKey(slice_id: number, frame: number, x: number, y: number, width: number, height: number, center_x?: number | null, center_y?: number | null, center_width?: number | null, center_height?: number | null, pivot_x?: number | null, pivot_y?: number | null): void;
1101
+ /**
1102
+ * Mirror the gesture in progress (symmetry): every pixel it paints is
1103
+ * also painted at its mirror images. `axis_x2` / `axis_y2` are the
1104
+ * vertical / horizontal axis in half pixels from the left / top canvas
1105
+ * edge (column `x` mirrors to `axis_x2 − 1 − x`); absent turns that
1106
+ * axis off. Mirror images off the canvas are skipped unless the
1107
+ * gesture wraps. Call it after `beginStroke` / `beginShadingStroke`
1108
+ * and before the first [`Self::stroke_to`].
1109
+ *
1110
+ * Errors when no gesture is armed or it has already painted.
1111
+ */
1112
+ setStrokeMirror(axis_x2?: number | null, axis_y2?: number | null): void;
1113
+ /**
1114
+ * Let the gesture in progress wrap across the canvas edges (tiled
1115
+ * mode): along a wrapped axis, points beyond the canvas are taken
1116
+ * modulo the canvas size instead of skipped, and the line between two
1117
+ * points continues at the opposite edge. Call it after `beginStroke` /
1118
+ * `beginShadingStroke` and before the first [`Self::stroke_to`].
1119
+ *
1120
+ * Errors when no gesture is armed or it has already painted.
1121
+ */
1122
+ setStrokeWrap(x: boolean, y: boolean): void;
1017
1123
  /**
1018
1124
  * Set the playback direction of the tag at `index` by snake_case
1019
1125
  * name. One undo entry.
@@ -1067,14 +1173,14 @@ export class Document {
1067
1173
  */
1068
1174
  sliceKeyCenterWidth(slice_id: number, key_index: number): number;
1069
1175
  /**
1070
- * Sprite-space `x` of the key's 9-patch center, or `0` when the
1071
- * key has no center. Errors when `slice_id` or `key_index` is
1072
- * out of range.
1176
+ * `x` of the key's 9-patch center, relative to the key's bounds
1177
+ * origin, or `0` when the key has no center. Errors when
1178
+ * `slice_id` or `key_index` is out of range.
1073
1179
  */
1074
1180
  sliceKeyCenterX(slice_id: number, key_index: number): number;
1075
1181
  /**
1076
- * Sprite-space `y` of the key's 9-patch center, or `0` when the
1077
- * key has no center.
1182
+ * `y` of the key's 9-patch center, relative to the key's bounds
1183
+ * origin, or `0` when the key has no center.
1078
1184
  */
1079
1185
  sliceKeyCenterY(slice_id: number, key_index: number): number;
1080
1186
  /**
@@ -1103,13 +1209,13 @@ export class Document {
1103
1209
  */
1104
1210
  sliceKeyHeight(slice_id: number, key_index: number): number;
1105
1211
  /**
1106
- * Sprite-space `x` of the key's pivot, or `0` when the key has
1107
- * no pivot.
1212
+ * `x` of the key's pivot, relative to the key's bounds origin
1213
+ * (may be negative), or `0` when the key has no pivot.
1108
1214
  */
1109
1215
  sliceKeyPivotX(slice_id: number, key_index: number): number;
1110
1216
  /**
1111
- * Sprite-space `y` of the key's pivot, or `0` when the key has
1112
- * no pivot.
1217
+ * `y` of the key's pivot, relative to the key's bounds origin
1218
+ * (may be negative), or `0` when the key has no pivot.
1113
1219
  */
1114
1220
  sliceKeyPivotY(slice_id: number, key_index: number): number;
1115
1221
  /**
@@ -1243,6 +1349,12 @@ export class Document {
1243
1349
  * follow-up).
1244
1350
  */
1245
1351
  undo(): boolean;
1352
+ /**
1353
+ * A [`Vectorizer`] over `frame` composed like
1354
+ * [`exportPng`](Document::export_png): zoom 1, visible layers, no onion
1355
+ * skin, no overlays.
1356
+ */
1357
+ vectorizer(frame: number): Vectorizer;
1246
1358
  /**
1247
1359
  * Frame the UI is currently viewing / editing (0-based). All paint
1248
1360
  * paths target it. See [`Document::set_current_frame`].
@@ -1252,6 +1364,26 @@ export class Document {
1252
1364
  * Number of frames in the document.
1253
1365
  */
1254
1366
  readonly frameCount: number;
1367
+ /**
1368
+ * Grid cell height in sprite pixels (16 for a sprite without a
1369
+ * stored grid; 0 when a file stored a zero-sized grid).
1370
+ */
1371
+ readonly gridHeight: number;
1372
+ /**
1373
+ * Grid cell width in sprite pixels (16 for a sprite without a stored
1374
+ * grid; 0 when a file stored a zero-sized grid).
1375
+ */
1376
+ readonly gridWidth: number;
1377
+ /**
1378
+ * Grid x offset in sprite pixels (0 for a sprite without a stored
1379
+ * grid).
1380
+ */
1381
+ readonly gridX: number;
1382
+ /**
1383
+ * Grid y offset in sprite pixels (0 for a sprite without a stored
1384
+ * grid).
1385
+ */
1386
+ readonly gridY: number;
1255
1387
  /**
1256
1388
  * `true` when a non-empty marquee selection is active. See
1257
1389
  * [`pincel_core::Sprite::has_selection`].
@@ -1380,6 +1512,46 @@ export class Event {
1380
1512
  readonly y: number;
1381
1513
  }
1382
1514
 
1515
+ /**
1516
+ * The SVG of one trace and its counts.
1517
+ */
1518
+ export class VectorizeResult {
1519
+ private constructor();
1520
+ free(): void;
1521
+ [Symbol.dispose](): void;
1522
+ /**
1523
+ * Number of layers (one per colour).
1524
+ */
1525
+ readonly layers: number;
1526
+ /**
1527
+ * Number of outlines over all layers.
1528
+ */
1529
+ readonly outlines: number;
1530
+ /**
1531
+ * The SVG document.
1532
+ */
1533
+ readonly svg: string;
1534
+ /**
1535
+ * The monochrome threshold used, or −1 outside monochrome mode.
1536
+ */
1537
+ readonly threshold: number;
1538
+ }
1539
+
1540
+ /**
1541
+ * Traces one source image repeatedly; keeps the core's caches between
1542
+ * traces so a preview that changes only Potrace options stays cheap.
1543
+ */
1544
+ export class Vectorizer {
1545
+ private constructor();
1546
+ free(): void;
1547
+ [Symbol.dispose](): void;
1548
+ /**
1549
+ * Traces with `mode` (0 colours, 1 monochrome, 2 pixel-exact) and the
1550
+ * flat `params` vector; errors carry the core's message.
1551
+ */
1552
+ trace(mode: number, params: Float64Array): VectorizeResult;
1553
+ }
1554
+
1383
1555
  /**
1384
1556
  * Snake_case names of every blend mode, in file-format order.
1385
1557
  */
@@ -1391,6 +1563,13 @@ export function blendModeNames(): string[];
1391
1563
  */
1392
1564
  export function effectNames(): string[];
1393
1565
 
1566
+ /**
1567
+ * Number of [`Document`]s alive in this module (created and not yet
1568
+ * freed). A diagnostic: tests check that closing a tab frees its document
1569
+ * (docs/specs/document-tabs.md AC-16).
1570
+ */
1571
+ export function openDocumentCount(): number;
1572
+
1394
1573
  /**
1395
1574
  * A single composited frame returned to JS.
1396
1575
  *
@@ -1442,17 +1621,20 @@ export interface InitOutput {
1442
1621
  readonly document_clearSelection: (a: number) => void;
1443
1622
  readonly document_compose: (a: number, b: number, c: number) => [number, number, number];
1444
1623
  readonly document_composeDirty: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => [number, number, number];
1624
+ readonly document_composeFrame: (a: number, b: number, c: number, d: number) => [number, number, number];
1445
1625
  readonly document_currentFrame: (a: number) => number;
1446
1626
  readonly document_deleteSelection: (a: number) => [number, number, number];
1447
1627
  readonly document_drainEvents: (a: number) => [number, number];
1448
1628
  readonly document_endStroke: (a: number) => void;
1449
- readonly document_exportAtlas: (a: number, b: number, c: number, d: number, e: number, f: number) => [number, number, number];
1629
+ readonly document_exportAtlas: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => [number, number, number];
1450
1630
  readonly document_exportGpl: (a: number, b: number, c: number) => [number, number];
1451
- readonly document_exportPng: (a: number, b: number) => [number, number, number, number];
1631
+ readonly document_exportPalette: (a: number, b: number, c: number, d: number, e: number, f: number) => [number, number, number, number];
1632
+ readonly document_exportPng: (a: number, b: number, c: number) => [number, number, number, number];
1452
1633
  readonly document_frameCount: (a: number) => number;
1453
1634
  readonly document_hasSelection: (a: number) => number;
1454
1635
  readonly document_height: (a: number) => number;
1455
1636
  readonly document_importGpl: (a: number, b: number, c: number) => [number, number, number];
1637
+ readonly document_importPalette: (a: number, b: number, c: number) => [number, number, number];
1456
1638
  readonly document_layerCount: (a: number) => number;
1457
1639
  readonly document_layerIdAt: (a: number, b: number) => [number, number, number];
1458
1640
  readonly document_layerKind: (a: number, b: number) => [number, number];
@@ -1519,34 +1701,71 @@ export interface InitOutput {
1519
1701
  readonly document_undoDepth: (a: number) => number;
1520
1702
  readonly document_width: (a: number) => number;
1521
1703
  readonly palettePresetNames: () => [number, number];
1704
+ readonly openDocumentCount: () => number;
1705
+ readonly document_contractSelection: (a: number, b: number) => void;
1706
+ readonly document_expandSelection: (a: number, b: number) => void;
1707
+ readonly document_importPngAsLayer: (a: number, b: number, c: number, d: number, e: number) => [number, number, number];
1708
+ readonly document_invertSelection: (a: number) => void;
1709
+ readonly document_openPng: (a: number, b: number) => [number, number, number];
1710
+ readonly document_selectAll: (a: number) => void;
1711
+ readonly document_selectEllipse: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => [number, number];
1712
+ readonly document_selectPolygon: (a: number, b: number, c: number, d: number, e: number) => [number, number];
1713
+ readonly document_selectRect: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => [number, number];
1714
+ readonly document_selectWand: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number) => [number, number];
1715
+ readonly document_selectionIsRect: (a: number) => number;
1716
+ readonly document_selectionMask: (a: number) => [number, number];
1717
+ readonly __wbg_vectorizer_free: (a: number, b: number) => void;
1718
+ readonly __wbg_vectorizeresult_free: (a: number, b: number) => void;
1719
+ readonly document_addTag: (a: number, b: number, c: number, d: number, e: number, f: number) => [number, number, number];
1720
+ readonly document_applyEffect: (a: number, b: number, c: number, d: number, e: number) => [number, number, number];
1721
+ readonly document_applyGradient: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number) => [number, number, number];
1722
+ readonly document_applyShape: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number, k: number, l: number, m: number) => [number, number];
1723
+ readonly document_frameDuration: (a: number, b: number) => [number, number, number];
1724
+ readonly document_gridHeight: (a: number) => number;
1725
+ readonly document_gridWidth: (a: number) => number;
1726
+ readonly document_gridX: (a: number) => number;
1727
+ readonly document_gridY: (a: number) => number;
1728
+ readonly document_onionSkinEnabled: (a: number) => number;
1729
+ readonly document_previewEffect: (a: number, b: number, c: number, d: number, e: number, f: number) => [number, number, number];
1730
+ readonly document_removeFrame: (a: number, b: number) => [number, number];
1731
+ readonly document_removeTag: (a: number, b: number) => [number, number];
1732
+ readonly document_setFrameDuration: (a: number, b: number, c: number) => [number, number];
1733
+ readonly document_setGrid: (a: number, b: number, c: number, d: number, e: number) => [number, number];
1734
+ readonly document_setOnionSkin: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
1735
+ readonly document_setTagDirection: (a: number, b: number, c: number, d: number) => [number, number];
1736
+ readonly document_setTagName: (a: number, b: number, c: number, d: number) => [number, number];
1737
+ readonly document_setTagRange: (a: number, b: number, c: number, d: number) => [number, number];
1738
+ readonly document_tagColor: (a: number, b: number) => [number, number, number];
1739
+ readonly document_tagCount: (a: number) => number;
1740
+ readonly document_tagDirection: (a: number, b: number) => [number, number, number, number];
1741
+ readonly document_tagFrom: (a: number, b: number) => [number, number, number];
1742
+ readonly document_tagName: (a: number, b: number) => [number, number, number, number];
1743
+ readonly document_tagTo: (a: number, b: number) => [number, number, number];
1744
+ readonly document_vectorizer: (a: number, b: number) => [number, number, number];
1745
+ readonly effectNames: () => [number, number];
1746
+ readonly vectorizer_trace: (a: number, b: number, c: number, d: number) => [number, number, number];
1747
+ readonly vectorizeresult_layers: (a: number) => number;
1748
+ readonly vectorizeresult_outlines: (a: number) => number;
1749
+ readonly vectorizeresult_svg: (a: number) => [number, number];
1750
+ readonly vectorizeresult_threshold: (a: number) => number;
1522
1751
  readonly __wbg_animationinfo_free: (a: number, b: number) => void;
1523
- readonly __wbg_event_free: (a: number, b: number) => void;
1524
1752
  readonly animationinfo_defaultLoops: (a: number) => number;
1525
1753
  readonly animationinfo_frameCount: (a: number) => number;
1526
1754
  readonly animationinfo_gifApproximated: (a: number) => number;
1527
1755
  readonly animationinfo_semiTransparent: (a: number) => number;
1528
1756
  readonly document_animationInfo: (a: number, b: number, c: number) => [number, number, number];
1529
1757
  readonly document_exportAnimation: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => [number, number, number, number];
1758
+ readonly __wbg_event_free: (a: number, b: number) => void;
1530
1759
  readonly event_frame: (a: number) => number;
1531
1760
  readonly event_height: (a: number) => number;
1532
1761
  readonly event_kind: (a: number) => [number, number];
1762
+ readonly event_layer: (a: number) => number;
1533
1763
  readonly event_width: (a: number) => number;
1534
1764
  readonly event_x: (a: number) => number;
1535
1765
  readonly event_y: (a: number) => number;
1536
- readonly event_layer: (a: number) => number;
1537
- readonly __wbg_copiedimage_free: (a: number, b: number) => void;
1538
- readonly copiedimage_height: (a: number) => number;
1539
- readonly copiedimage_png: (a: number) => [number, number];
1540
- readonly copiedimage_width: (a: number) => number;
1541
- readonly copiedimage_x: (a: number) => number;
1542
- readonly copiedimage_y: (a: number) => number;
1543
- readonly document_copySelection: (a: number, b: number) => [number, number, number];
1544
- readonly document_cutSelection: (a: number) => [number, number, number];
1545
- readonly document_imageKey: (a: number, b: number) => [number, number, number, number];
1546
- readonly document_pasteLayer: (a: number, b: number, c: number, d: number, e: number, f: number) => [number, number, number];
1547
1766
  readonly blendModeNames: () => [number, number];
1548
1767
  readonly document_addGroup: (a: number, b: number, c: number) => [number, number, number];
1549
- readonly document_beginStroke: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number) => [number, number];
1768
+ readonly document_drawText: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number, k: number, l: number, m: number) => [number, number, number];
1550
1769
  readonly document_duplicateLayer: (a: number, b: number) => [number, number, number];
1551
1770
  readonly document_flattenImage: (a: number) => [number, number, number];
1552
1771
  readonly document_layerBlendMode: (a: number, b: number) => [number, number];
@@ -1557,51 +1776,32 @@ export interface InitOutput {
1557
1776
  readonly document_layerThumbnail: (a: number, b: number, c: number, d: number) => [number, number, number];
1558
1777
  readonly document_mergeDown: (a: number, b: number) => [number, number];
1559
1778
  readonly document_moveLayerTo: (a: number, b: number, c: number, d: number, e: number) => [number, number];
1779
+ readonly document_previewText: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number, k: number, l: number, m: number, n: number) => [number, number, number];
1560
1780
  readonly document_reorderLayer: (a: number, b: number, c: number) => [number, number];
1561
1781
  readonly document_setLayerBlendMode: (a: number, b: number, c: number, d: number) => [number, number];
1562
1782
  readonly document_setLayerEditable: (a: number, b: number, c: number) => [number, number];
1563
1783
  readonly document_setLayerOpacity: (a: number, b: number, c: number) => [number, number];
1784
+ readonly registerFont: (a: number, b: number) => number;
1785
+ readonly document_beginShadingStroke: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number) => [number, number];
1786
+ readonly document_beginStroke: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number) => [number, number];
1787
+ readonly document_setStrokeMirror: (a: number, b: number, c: number) => [number, number];
1788
+ readonly document_setStrokeWrap: (a: number, b: number, c: number) => [number, number];
1564
1789
  readonly document_strokeTo: (a: number, b: number, c: number, d: number) => [number, number];
1565
- readonly document_addTag: (a: number, b: number, c: number, d: number, e: number, f: number) => [number, number, number];
1790
+ readonly __wbg_copiedimage_free: (a: number, b: number) => void;
1791
+ readonly copiedimage_height: (a: number) => number;
1792
+ readonly copiedimage_png: (a: number) => [number, number];
1793
+ readonly copiedimage_width: (a: number) => number;
1794
+ readonly copiedimage_x: (a: number) => number;
1795
+ readonly copiedimage_y: (a: number) => number;
1796
+ readonly document_copySelection: (a: number, b: number) => [number, number, number];
1566
1797
  readonly document_cropToSelection: (a: number) => [number, number, number];
1567
- readonly document_frameDuration: (a: number, b: number) => [number, number, number];
1568
- readonly document_onionSkinEnabled: (a: number) => number;
1569
- readonly document_removeFrame: (a: number, b: number) => [number, number];
1570
- readonly document_removeTag: (a: number, b: number) => [number, number];
1798
+ readonly document_cutSelection: (a: number) => [number, number, number];
1799
+ readonly document_imageKey: (a: number, b: number) => [number, number, number, number];
1800
+ readonly document_pasteLayer: (a: number, b: number, c: number, d: number, e: number, f: number) => [number, number, number];
1571
1801
  readonly document_resizeCanvas: (a: number, b: number, c: number, d: number, e: number) => [number, number];
1572
1802
  readonly document_scaleImage: (a: number, b: number, c: number, d: number, e: number) => [number, number];
1573
- readonly document_setFrameDuration: (a: number, b: number, c: number) => [number, number];
1574
- readonly document_setOnionSkin: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
1575
- readonly document_setTagDirection: (a: number, b: number, c: number, d: number) => [number, number];
1576
- readonly document_setTagName: (a: number, b: number, c: number, d: number) => [number, number];
1577
- readonly document_setTagRange: (a: number, b: number, c: number, d: number) => [number, number];
1578
- readonly document_tagColor: (a: number, b: number) => [number, number, number];
1579
- readonly document_tagCount: (a: number) => number;
1580
- readonly document_tagDirection: (a: number, b: number) => [number, number, number, number];
1581
- readonly document_tagFrom: (a: number, b: number) => [number, number, number];
1582
- readonly document_tagName: (a: number, b: number) => [number, number, number, number];
1583
- readonly document_tagTo: (a: number, b: number) => [number, number, number];
1584
1803
  readonly document_transformCanvas: (a: number, b: number, c: number) => [number, number];
1585
1804
  readonly document_transformLayer: (a: number, b: number, c: number) => [number, number];
1586
- readonly document_contractSelection: (a: number, b: number) => void;
1587
- readonly document_drawText: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number, k: number, l: number, m: number) => [number, number, number];
1588
- readonly document_expandSelection: (a: number, b: number) => void;
1589
- readonly document_invertSelection: (a: number) => void;
1590
- readonly document_previewText: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number, k: number, l: number, m: number, n: number) => [number, number, number];
1591
- readonly document_selectAll: (a: number) => void;
1592
- readonly document_selectEllipse: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => [number, number];
1593
- readonly document_selectPolygon: (a: number, b: number, c: number, d: number, e: number) => [number, number];
1594
- readonly document_selectRect: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => [number, number];
1595
- readonly document_selectWand: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number) => [number, number];
1596
- readonly document_selectionIsRect: (a: number) => number;
1597
- readonly document_selectionMask: (a: number) => [number, number];
1598
- readonly registerFont: (a: number, b: number) => number;
1599
- readonly document_applyEffect: (a: number, b: number, c: number, d: number, e: number) => [number, number, number];
1600
- readonly document_applyShape: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number, k: number, l: number, m: number) => [number, number];
1601
- readonly document_previewEffect: (a: number, b: number, c: number, d: number, e: number, f: number) => [number, number, number];
1602
- readonly effectNames: () => [number, number];
1603
- readonly document_importPngAsLayer: (a: number, b: number, c: number, d: number, e: number) => [number, number, number];
1604
- readonly document_openPng: (a: number, b: number) => [number, number, number];
1605
1805
  readonly __wbindgen_externrefs: WebAssembly.Table;
1606
1806
  readonly __wbindgen_free: (a: number, b: number, c: number) => void;
1607
1807
  readonly __externref_drop_slice: (a: number, b: number) => void;
package/pincel_wasm.js CHANGED
@@ -464,9 +464,10 @@ export class Document {
464
464
  * stable across runs and monotonic. Returns the assigned id.
465
465
  *
466
466
  * Routes through the [`AddTileset`] command so the operation joins
467
- * the undo / redo bus. Tile-image content starts empty (Aseprite
468
- * convention: tile id `0` is the implicit empty tile); per-tile
469
- * edits land alongside the Tileset Editor in M8.7.
467
+ * the undo / redo bus. The tileset starts with one stored, fully
468
+ * transparent tile `0` (Aseprite's empty tile), so the first
469
+ * [`Document::add_tile`] returns id `1` and no user tile is written
470
+ * as the empty tile (docs/specs/tilemaps.md, Decisions 2026-10-29).
470
471
  *
471
472
  * Errors when `tile_w` or `tile_h` is zero, when the existing id
472
473
  * space is exhausted (an existing tileset already uses `u32::MAX`),
@@ -587,6 +588,38 @@ export class Document {
587
588
  throw takeFromExternrefTable0(ret[0]);
588
589
  }
589
590
  }
591
+ /**
592
+ * Fill the selection — or, without one, the active layer's cel on the
593
+ * current frame — with a dithered ramp from `foreground` at the drag
594
+ * start to `background` at the drag end, as one undo entry.
595
+ *
596
+ * - `line`: `[x0, y0, x1, y1]`, the drag's start and end sprite pixels.
597
+ * - `kind`: `linear` or `radial`.
598
+ * - `dither`: the Bayer matrix size `2`, `4` or `8`, or `0` for two
599
+ * hard bands split halfway.
600
+ * - `foreground` / `background`: `0xRRGGBBAA`.
601
+ *
602
+ * Returns `false` — and changes nothing — for a zero-length drag.
603
+ * Errors (and changes nothing) on a locked layer, a document without a
604
+ * paintable image layer, and an indexed or grayscale sprite.
605
+ * @param {Int32Array} line
606
+ * @param {string} kind
607
+ * @param {number} dither
608
+ * @param {number} foreground
609
+ * @param {number} background
610
+ * @returns {boolean}
611
+ */
612
+ applyGradient(line, kind, dither, foreground, background) {
613
+ const ptr0 = passArray32ToWasm0(line, wasm.__wbindgen_malloc);
614
+ const len0 = WASM_VECTOR_LEN;
615
+ const ptr1 = passStringToWasm0(kind, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
616
+ const len1 = WASM_VECTOR_LEN;
617
+ const ret = wasm.document_applyGradient(this.__wbg_ptr, ptr0, len0, ptr1, len1, dither, foreground, background);
618
+ if (ret[2]) {
619
+ throw takeFromExternrefTable0(ret[1]);
620
+ }
621
+ return ret[0] !== 0;
622
+ }
590
623
  /**
591
624
  * Rasterize a 1-pixel-wide Bresenham line between sprite-space
592
625
  * `(x0, y0)` and `(x1, y1)` with the given non-premultiplied RGBA
@@ -749,6 +782,37 @@ export class Document {
749
782
  throw takeFromExternrefTable0(ret[0]);
750
783
  }
751
784
  }
785
+ /**
786
+ * Start a Pencil gesture with the Shading ink: every pixel the stroke
787
+ * touches whose color before the stroke is exactly entry `i` of `ramp`
788
+ * becomes entry `i + step`, clamped to the ramp; other colors stay.
789
+ * Each pixel changes at most once per gesture. Continue it with
790
+ * [`Self::stroke_to`] and close it with `endStroke` like any stroke.
791
+ *
792
+ * - `ramp`: the colors in palette order (`0xRRGGBBAA`), at least one.
793
+ * - `step`: `1` (left button, toward the end) or `-1` (right button,
794
+ * toward the start).
795
+ * - `size`, `shape`, `pixel_perfect`: as in [`Self::begin_stroke`].
796
+ *
797
+ * Errors (and starts nothing) for an empty ramp, another step, an
798
+ * unknown shape, a locked target layer, or a document without a
799
+ * paintable image layer.
800
+ * @param {Uint32Array} ramp
801
+ * @param {number} step
802
+ * @param {number} size
803
+ * @param {string} shape
804
+ * @param {boolean} pixel_perfect
805
+ */
806
+ beginShadingStroke(ramp, step, size, shape, pixel_perfect) {
807
+ const ptr0 = passArray32ToWasm0(ramp, wasm.__wbindgen_malloc);
808
+ const len0 = WASM_VECTOR_LEN;
809
+ const ptr1 = passStringToWasm0(shape, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
810
+ const len1 = WASM_VECTOR_LEN;
811
+ const ret = wasm.document_beginShadingStroke(this.__wbg_ptr, ptr0, len0, step, size, ptr1, len1, pixel_perfect);
812
+ if (ret[1]) {
813
+ throw takeFromExternrefTable0(ret[0]);
814
+ }
815
+ }
752
816
  /**
753
817
  * Start a Pencil / Eraser gesture on the active layer / current frame.
754
818
  * Nothing is painted until the first [`Self::stroke_to`].
@@ -838,6 +902,24 @@ export class Document {
838
902
  }
839
903
  return ComposeFrame.__wrap(ret[0]);
840
904
  }
905
+ /**
906
+ * [`Document::compose`] with the onion skin chosen per call: `onion =
907
+ * true` applies the configured onion skin (the same bytes as
908
+ * `compose`), `onion = false` leaves it out whatever
909
+ * [`Document::set_onion_skin`] says — for an animation preview that
910
+ * must never show ghosts (docs/specs/animation-preview.md).
911
+ * @param {number} frame
912
+ * @param {number} zoom
913
+ * @param {boolean} onion
914
+ * @returns {ComposeFrame}
915
+ */
916
+ composeFrame(frame, zoom, onion) {
917
+ const ret = wasm.document_composeFrame(this.__wbg_ptr, frame, zoom, onion);
918
+ if (ret[2]) {
919
+ throw takeFromExternrefTable0(ret[1]);
920
+ }
921
+ return ComposeFrame.__wrap(ret[0]);
922
+ }
841
923
  /**
842
924
  * Shrink the selection by `radius` pixels (may clear it).
843
925
  * @param {number} radius
@@ -1002,7 +1084,7 @@ export class Document {
1002
1084
  * a fresh `Uint8Array` copy. Errors surface the `pincel-core`
1003
1085
  * message: an unknown format or tag, a scale outside 1–10, an output
1004
1086
  * edge above 16384 px, a frameless sequence, or a sprite the renderer
1005
- * refuses (an indexed sprite).
1087
+ * refuses (a corrupt cel or a broken linked cel).
1006
1088
  * @param {string} format
1007
1089
  * @param {string | null | undefined} tag
1008
1090
  * @param {number} scale
@@ -1039,17 +1121,24 @@ export class Document {
1039
1121
  * `meta.image` names `image_name` (default `"sheet.png"`). Errors
1040
1122
  * surface the underlying `pincel-core` message: zero columns, an
1041
1123
  * unknown tag, a frameless sprite, or anything the renderer refuses.
1124
+ *
1125
+ * `scale` (optional, default 1) upscales the sheet by an integer
1126
+ * factor 1–10 with nearest-neighbour; the manifest and the `--data`
1127
+ * JSON describe the scaled sheet (`meta.scale` stays `"1"`, as
1128
+ * Aseprite's `--scale`). A scale outside 1–10 or a sheet edge above
1129
+ * 16384 px is an error naming the limit (docs/specs/scaled-export.md).
1042
1130
  * @param {number} columns
1043
1131
  * @param {string | null} [tag]
1044
1132
  * @param {string | null} [image_name]
1133
+ * @param {number | null} [scale]
1045
1134
  * @returns {AtlasExport}
1046
1135
  */
1047
- exportAtlas(columns, tag, image_name) {
1136
+ exportAtlas(columns, tag, image_name, scale) {
1048
1137
  var ptr0 = isLikeNone(tag) ? 0 : passStringToWasm0(tag, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
1049
1138
  var len0 = WASM_VECTOR_LEN;
1050
1139
  var ptr1 = isLikeNone(image_name) ? 0 : passStringToWasm0(image_name, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
1051
1140
  var len1 = WASM_VECTOR_LEN;
1052
- const ret = wasm.document_exportAtlas(this.__wbg_ptr, columns, ptr0, len0, ptr1, len1);
1141
+ const ret = wasm.document_exportAtlas(this.__wbg_ptr, columns, ptr0, len0, ptr1, len1, isLikeNone(scale) ? Number.MAX_SAFE_INTEGER : (scale) >>> 0);
1053
1142
  if (ret[2]) {
1054
1143
  throw takeFromExternrefTable0(ret[1]);
1055
1144
  }
@@ -1057,6 +1146,9 @@ export class Document {
1057
1146
  }
1058
1147
  /**
1059
1148
  * The palette as a GIMP `.gpl` file called `name` (alpha dropped).
1149
+ *
1150
+ * Deprecated: use [`Document::export_palette`] (`exportPalette`) with
1151
+ * format `gpl`. Kept for the public npm API (spec §17.5).
1060
1152
  * @param {string} name
1061
1153
  * @returns {string}
1062
1154
  */
@@ -1074,6 +1166,30 @@ export class Document {
1074
1166
  wasm.__wbindgen_free(deferred2_0, deferred2_1, 1);
1075
1167
  }
1076
1168
  }
1169
+ /**
1170
+ * The palette as a file: `format` is `gpl` (a GIMP palette called
1171
+ * `name`), `hex` (Lospec), `pal` (JASC) or `png` (a one-row strip of
1172
+ * `cell` × `cell` px swatches). `name` is used only by `gpl`, `cell`
1173
+ * only by `png`. Errors for an unknown format, or a PNG strip of an
1174
+ * empty palette or with `cell` 0.
1175
+ * @param {string} format
1176
+ * @param {string} name
1177
+ * @param {number} cell
1178
+ * @returns {Uint8Array}
1179
+ */
1180
+ exportPalette(format, name, cell) {
1181
+ const ptr0 = passStringToWasm0(format, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
1182
+ const len0 = WASM_VECTOR_LEN;
1183
+ const ptr1 = passStringToWasm0(name, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
1184
+ const len1 = WASM_VECTOR_LEN;
1185
+ const ret = wasm.document_exportPalette(this.__wbg_ptr, ptr0, len0, ptr1, len1, cell);
1186
+ if (ret[3]) {
1187
+ throw takeFromExternrefTable0(ret[2]);
1188
+ }
1189
+ var v3 = getArrayU8FromWasm0(ret[0], ret[1]).slice();
1190
+ wasm.__wbindgen_free(ret[0], ret[1] * 1, 1);
1191
+ return v3;
1192
+ }
1077
1193
  /**
1078
1194
  * Encode one frame as an RGBA8 PNG.
1079
1195
  *
@@ -1086,11 +1202,17 @@ export class Document {
1086
1202
  * `pincel-core` message: an out-of-range frame, or a sprite the
1087
1203
  * renderer refuses (non-RGBA color mode, non-`Normal` blend mode,
1088
1204
  * group layer, linked cel).
1205
+ *
1206
+ * `scale` (optional, default 1) upscales the PNG by an integer factor
1207
+ * 1–10 with nearest-neighbour (docs/specs/scaled-export.md); scale 1
1208
+ * and no scale give the same bytes. A scale outside 1–10 or an output
1209
+ * edge above 16384 px is an error naming the limit.
1089
1210
  * @param {number} frame
1211
+ * @param {number | null} [scale]
1090
1212
  * @returns {Uint8Array}
1091
1213
  */
1092
- exportPng(frame) {
1093
- const ret = wasm.document_exportPng(this.__wbg_ptr, frame);
1214
+ exportPng(frame, scale) {
1215
+ const ret = wasm.document_exportPng(this.__wbg_ptr, frame, isLikeNone(scale) ? Number.MAX_SAFE_INTEGER : (scale) >>> 0);
1094
1216
  if (ret[3]) {
1095
1217
  throw takeFromExternrefTable0(ret[2]);
1096
1218
  }
@@ -1132,6 +1254,42 @@ export class Document {
1132
1254
  }
1133
1255
  return ret[0];
1134
1256
  }
1257
+ /**
1258
+ * Grid cell height in sprite pixels (16 for a sprite without a
1259
+ * stored grid; 0 when a file stored a zero-sized grid).
1260
+ * @returns {number}
1261
+ */
1262
+ get gridHeight() {
1263
+ const ret = wasm.document_gridHeight(this.__wbg_ptr);
1264
+ return ret >>> 0;
1265
+ }
1266
+ /**
1267
+ * Grid cell width in sprite pixels (16 for a sprite without a stored
1268
+ * grid; 0 when a file stored a zero-sized grid).
1269
+ * @returns {number}
1270
+ */
1271
+ get gridWidth() {
1272
+ const ret = wasm.document_gridWidth(this.__wbg_ptr);
1273
+ return ret >>> 0;
1274
+ }
1275
+ /**
1276
+ * Grid x offset in sprite pixels (0 for a sprite without a stored
1277
+ * grid).
1278
+ * @returns {number}
1279
+ */
1280
+ get gridX() {
1281
+ const ret = wasm.document_gridX(this.__wbg_ptr);
1282
+ return ret;
1283
+ }
1284
+ /**
1285
+ * Grid y offset in sprite pixels (0 for a sprite without a stored
1286
+ * grid).
1287
+ * @returns {number}
1288
+ */
1289
+ get gridY() {
1290
+ const ret = wasm.document_gridY(this.__wbg_ptr);
1291
+ return ret;
1292
+ }
1135
1293
  /**
1136
1294
  * `true` when a non-empty marquee selection is active. See
1137
1295
  * [`pincel_core::Sprite::has_selection`].
@@ -1179,6 +1337,10 @@ export class Document {
1179
1337
  /**
1180
1338
  * Replace the palette with a GIMP `.gpl` file's colours and return
1181
1339
  * how many it holds. One undo entry. Refused for indexed documents.
1340
+ *
1341
+ * Deprecated: use [`Document::import_palette`] (`importPalette`),
1342
+ * which reads `.gpl` and the other palette formats. Kept for the
1343
+ * public npm API (spec §17.5).
1182
1344
  * @param {string} text
1183
1345
  * @returns {number}
1184
1346
  */
@@ -1191,6 +1353,25 @@ export class Document {
1191
1353
  }
1192
1354
  return ret[0] >>> 0;
1193
1355
  }
1356
+ /**
1357
+ * Replace the palette with a palette file's colours and return how
1358
+ * many it holds. The format — GIMP `.gpl`, Lospec `.hex`, JASC `.pal`
1359
+ * or a PNG palette image — is detected from the content, not the file
1360
+ * name (spec §3.7). One undo entry. Refused for indexed documents, for
1361
+ * files without colours and above 256 colours; the palette is then
1362
+ * unchanged.
1363
+ * @param {Uint8Array} bytes
1364
+ * @returns {number}
1365
+ */
1366
+ importPalette(bytes) {
1367
+ const ptr0 = passArray8ToWasm0(bytes, wasm.__wbindgen_malloc);
1368
+ const len0 = WASM_VECTOR_LEN;
1369
+ const ret = wasm.document_importPalette(this.__wbg_ptr, ptr0, len0);
1370
+ if (ret[2]) {
1371
+ throw takeFromExternrefTable0(ret[1]);
1372
+ }
1373
+ return ret[0] >>> 0;
1374
+ }
1194
1375
  /**
1195
1376
  * Decode PNG bytes and add them as a new image layer named `name` on
1196
1377
  * top of the stack, at the current frame, anchored at the canvas
@@ -2046,6 +2227,22 @@ export class Document {
2046
2227
  throw takeFromExternrefTable0(ret[0]);
2047
2228
  }
2048
2229
  }
2230
+ /**
2231
+ * Set the grid's offset (`x`, `y`) and cell size (`width` ×
2232
+ * `height`) as one undo entry; saved in the `.aseprite` header.
2233
+ * Errors, leaving the grid unchanged, for a cell size outside
2234
+ * 1–65535 or an offset outside −32768–32767.
2235
+ * @param {number} x
2236
+ * @param {number} y
2237
+ * @param {number} width
2238
+ * @param {number} height
2239
+ */
2240
+ setGrid(x, y, width, height) {
2241
+ const ret = wasm.document_setGrid(this.__wbg_ptr, x, y, width, height);
2242
+ if (ret[1]) {
2243
+ throw takeFromExternrefTable0(ret[0]);
2244
+ }
2245
+ }
2049
2246
  /**
2050
2247
  * Set the named layer's blend mode by name (see [`blend_mode_names`]),
2051
2248
  * routed through the undo bus. Emits `dirty-canvas`. Errors on an
@@ -2197,6 +2394,42 @@ export class Document {
2197
2394
  throw takeFromExternrefTable0(ret[0]);
2198
2395
  }
2199
2396
  }
2397
+ /**
2398
+ * Mirror the gesture in progress (symmetry): every pixel it paints is
2399
+ * also painted at its mirror images. `axis_x2` / `axis_y2` are the
2400
+ * vertical / horizontal axis in half pixels from the left / top canvas
2401
+ * edge (column `x` mirrors to `axis_x2 − 1 − x`); absent turns that
2402
+ * axis off. Mirror images off the canvas are skipped unless the
2403
+ * gesture wraps. Call it after `beginStroke` / `beginShadingStroke`
2404
+ * and before the first [`Self::stroke_to`].
2405
+ *
2406
+ * Errors when no gesture is armed or it has already painted.
2407
+ * @param {number | null} [axis_x2]
2408
+ * @param {number | null} [axis_y2]
2409
+ */
2410
+ setStrokeMirror(axis_x2, axis_y2) {
2411
+ const ret = wasm.document_setStrokeMirror(this.__wbg_ptr, isLikeNone(axis_x2) ? Number.MAX_SAFE_INTEGER : (axis_x2) >> 0, isLikeNone(axis_y2) ? Number.MAX_SAFE_INTEGER : (axis_y2) >> 0);
2412
+ if (ret[1]) {
2413
+ throw takeFromExternrefTable0(ret[0]);
2414
+ }
2415
+ }
2416
+ /**
2417
+ * Let the gesture in progress wrap across the canvas edges (tiled
2418
+ * mode): along a wrapped axis, points beyond the canvas are taken
2419
+ * modulo the canvas size instead of skipped, and the line between two
2420
+ * points continues at the opposite edge. Call it after `beginStroke` /
2421
+ * `beginShadingStroke` and before the first [`Self::stroke_to`].
2422
+ *
2423
+ * Errors when no gesture is armed or it has already painted.
2424
+ * @param {boolean} x
2425
+ * @param {boolean} y
2426
+ */
2427
+ setStrokeWrap(x, y) {
2428
+ const ret = wasm.document_setStrokeWrap(this.__wbg_ptr, x, y);
2429
+ if (ret[1]) {
2430
+ throw takeFromExternrefTable0(ret[0]);
2431
+ }
2432
+ }
2200
2433
  /**
2201
2434
  * Set the playback direction of the tag at `index` by snake_case
2202
2435
  * name. One undo entry.
@@ -2325,9 +2558,9 @@ export class Document {
2325
2558
  return ret[0] >>> 0;
2326
2559
  }
2327
2560
  /**
2328
- * Sprite-space `x` of the key's 9-patch center, or `0` when the
2329
- * key has no center. Errors when `slice_id` or `key_index` is
2330
- * out of range.
2561
+ * `x` of the key's 9-patch center, relative to the key's bounds
2562
+ * origin, or `0` when the key has no center. Errors when
2563
+ * `slice_id` or `key_index` is out of range.
2331
2564
  * @param {number} slice_id
2332
2565
  * @param {number} key_index
2333
2566
  * @returns {number}
@@ -2340,8 +2573,8 @@ export class Document {
2340
2573
  return ret[0];
2341
2574
  }
2342
2575
  /**
2343
- * Sprite-space `y` of the key's 9-patch center, or `0` when the
2344
- * key has no center.
2576
+ * `y` of the key's 9-patch center, relative to the key's bounds
2577
+ * origin, or `0` when the key has no center.
2345
2578
  * @param {number} slice_id
2346
2579
  * @param {number} key_index
2347
2580
  * @returns {number}
@@ -2420,8 +2653,8 @@ export class Document {
2420
2653
  return ret[0] >>> 0;
2421
2654
  }
2422
2655
  /**
2423
- * Sprite-space `x` of the key's pivot, or `0` when the key has
2424
- * no pivot.
2656
+ * `x` of the key's pivot, relative to the key's bounds origin
2657
+ * (may be negative), or `0` when the key has no pivot.
2425
2658
  * @param {number} slice_id
2426
2659
  * @param {number} key_index
2427
2660
  * @returns {number}
@@ -2434,8 +2667,8 @@ export class Document {
2434
2667
  return ret[0];
2435
2668
  }
2436
2669
  /**
2437
- * Sprite-space `y` of the key's pivot, or `0` when the key has
2438
- * no pivot.
2670
+ * `y` of the key's pivot, relative to the key's bounds origin
2671
+ * (may be negative), or `0` when the key has no pivot.
2439
2672
  * @param {number} slice_id
2440
2673
  * @param {number} key_index
2441
2674
  * @returns {number}
@@ -2779,6 +3012,20 @@ export class Document {
2779
3012
  const ret = wasm.document_undoDepth(this.__wbg_ptr);
2780
3013
  return ret >>> 0;
2781
3014
  }
3015
+ /**
3016
+ * A [`Vectorizer`] over `frame` composed like
3017
+ * [`exportPng`](Document::export_png): zoom 1, visible layers, no onion
3018
+ * skin, no overlays.
3019
+ * @param {number} frame
3020
+ * @returns {Vectorizer}
3021
+ */
3022
+ vectorizer(frame) {
3023
+ const ret = wasm.document_vectorizer(this.__wbg_ptr, frame);
3024
+ if (ret[2]) {
3025
+ throw takeFromExternrefTable0(ret[1]);
3026
+ }
3027
+ return Vectorizer.__wrap(ret[0]);
3028
+ }
2782
3029
  /**
2783
3030
  * Canvas width in pixels.
2784
3031
  * @returns {number}
@@ -2893,6 +3140,109 @@ export class Event {
2893
3140
  }
2894
3141
  if (Symbol.dispose) Event.prototype[Symbol.dispose] = Event.prototype.free;
2895
3142
 
3143
+ /**
3144
+ * The SVG of one trace and its counts.
3145
+ */
3146
+ export class VectorizeResult {
3147
+ static __wrap(ptr) {
3148
+ const obj = Object.create(VectorizeResult.prototype);
3149
+ obj.__wbg_ptr = ptr;
3150
+ VectorizeResultFinalization.register(obj, obj.__wbg_ptr, obj);
3151
+ return obj;
3152
+ }
3153
+ __destroy_into_raw() {
3154
+ const ptr = this.__wbg_ptr;
3155
+ this.__wbg_ptr = 0;
3156
+ VectorizeResultFinalization.unregister(this);
3157
+ return ptr;
3158
+ }
3159
+ free() {
3160
+ const ptr = this.__destroy_into_raw();
3161
+ wasm.__wbg_vectorizeresult_free(ptr, 0);
3162
+ }
3163
+ /**
3164
+ * Number of layers (one per colour).
3165
+ * @returns {number}
3166
+ */
3167
+ get layers() {
3168
+ const ret = wasm.vectorizeresult_layers(this.__wbg_ptr);
3169
+ return ret >>> 0;
3170
+ }
3171
+ /**
3172
+ * Number of outlines over all layers.
3173
+ * @returns {number}
3174
+ */
3175
+ get outlines() {
3176
+ const ret = wasm.vectorizeresult_outlines(this.__wbg_ptr);
3177
+ return ret >>> 0;
3178
+ }
3179
+ /**
3180
+ * The SVG document.
3181
+ * @returns {string}
3182
+ */
3183
+ get svg() {
3184
+ let deferred1_0;
3185
+ let deferred1_1;
3186
+ try {
3187
+ const ret = wasm.vectorizeresult_svg(this.__wbg_ptr);
3188
+ deferred1_0 = ret[0];
3189
+ deferred1_1 = ret[1];
3190
+ return getStringFromWasm0(ret[0], ret[1]);
3191
+ } finally {
3192
+ wasm.__wbindgen_free(deferred1_0, deferred1_1, 1);
3193
+ }
3194
+ }
3195
+ /**
3196
+ * The monochrome threshold used, or −1 outside monochrome mode.
3197
+ * @returns {number}
3198
+ */
3199
+ get threshold() {
3200
+ const ret = wasm.vectorizeresult_threshold(this.__wbg_ptr);
3201
+ return ret;
3202
+ }
3203
+ }
3204
+ if (Symbol.dispose) VectorizeResult.prototype[Symbol.dispose] = VectorizeResult.prototype.free;
3205
+
3206
+ /**
3207
+ * Traces one source image repeatedly; keeps the core's caches between
3208
+ * traces so a preview that changes only Potrace options stays cheap.
3209
+ */
3210
+ export class Vectorizer {
3211
+ static __wrap(ptr) {
3212
+ const obj = Object.create(Vectorizer.prototype);
3213
+ obj.__wbg_ptr = ptr;
3214
+ VectorizerFinalization.register(obj, obj.__wbg_ptr, obj);
3215
+ return obj;
3216
+ }
3217
+ __destroy_into_raw() {
3218
+ const ptr = this.__wbg_ptr;
3219
+ this.__wbg_ptr = 0;
3220
+ VectorizerFinalization.unregister(this);
3221
+ return ptr;
3222
+ }
3223
+ free() {
3224
+ const ptr = this.__destroy_into_raw();
3225
+ wasm.__wbg_vectorizer_free(ptr, 0);
3226
+ }
3227
+ /**
3228
+ * Traces with `mode` (0 colours, 1 monochrome, 2 pixel-exact) and the
3229
+ * flat `params` vector; errors carry the core's message.
3230
+ * @param {number} mode
3231
+ * @param {Float64Array} params
3232
+ * @returns {VectorizeResult}
3233
+ */
3234
+ trace(mode, params) {
3235
+ const ptr0 = passArrayF64ToWasm0(params, wasm.__wbindgen_malloc);
3236
+ const len0 = WASM_VECTOR_LEN;
3237
+ const ret = wasm.vectorizer_trace(this.__wbg_ptr, mode, ptr0, len0);
3238
+ if (ret[2]) {
3239
+ throw takeFromExternrefTable0(ret[1]);
3240
+ }
3241
+ return VectorizeResult.__wrap(ret[0]);
3242
+ }
3243
+ }
3244
+ if (Symbol.dispose) Vectorizer.prototype[Symbol.dispose] = Vectorizer.prototype.free;
3245
+
2896
3246
  /**
2897
3247
  * Snake_case names of every blend mode, in file-format order.
2898
3248
  * @returns {string[]}
@@ -2916,6 +3266,17 @@ export function effectNames() {
2916
3266
  return v1;
2917
3267
  }
2918
3268
 
3269
+ /**
3270
+ * Number of [`Document`]s alive in this module (created and not yet
3271
+ * freed). A diagnostic: tests check that closing a tab frees its document
3272
+ * (docs/specs/document-tabs.md AC-16).
3273
+ * @returns {number}
3274
+ */
3275
+ export function openDocumentCount() {
3276
+ const ret = wasm.openDocumentCount();
3277
+ return ret >>> 0;
3278
+ }
3279
+
2919
3280
  /**
2920
3281
  * A single composited frame returned to JS.
2921
3282
  *
@@ -2997,6 +3358,12 @@ const DocumentFinalization = (typeof FinalizationRegistry === 'undefined')
2997
3358
  const EventFinalization = (typeof FinalizationRegistry === 'undefined')
2998
3359
  ? { register: () => {}, unregister: () => {} }
2999
3360
  : new FinalizationRegistry(ptr => wasm.__wbg_event_free(ptr, 1));
3361
+ const VectorizeResultFinalization = (typeof FinalizationRegistry === 'undefined')
3362
+ ? { register: () => {}, unregister: () => {} }
3363
+ : new FinalizationRegistry(ptr => wasm.__wbg_vectorizeresult_free(ptr, 1));
3364
+ const VectorizerFinalization = (typeof FinalizationRegistry === 'undefined')
3365
+ ? { register: () => {}, unregister: () => {} }
3366
+ : new FinalizationRegistry(ptr => wasm.__wbg_vectorizer_free(ptr, 1));
3000
3367
 
3001
3368
  function getArrayJsValueFromWasm0(ptr, len) {
3002
3369
  ptr = ptr >>> 0;
Binary file