@pixerate/editor 0.270.0 → 0.271.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 (41) hide show
  1. package/dist/animation-editor/index.cjs +60 -60
  2. package/dist/animation-editor/index.js +3 -3
  3. package/dist/canvas/index.cjs +2 -2
  4. package/dist/canvas/index.js +1 -1
  5. package/dist/{chunk-4YSPQGZW.js → chunk-B5W677L7.js} +1 -1
  6. package/dist/{chunk-4NMPUJUK.cjs → chunk-DDL3ZBHK.cjs} +86 -86
  7. package/dist/{chunk-PY4GWSE2.cjs → chunk-EBFPMSJO.cjs} +27 -5
  8. package/dist/{chunk-56RHCIJV.cjs → chunk-JJ2H25JG.cjs} +237 -170
  9. package/dist/{chunk-CBVNCWJM.cjs → chunk-LBDC5434.cjs} +2 -2
  10. package/dist/{chunk-BENSE3VX.cjs → chunk-M2ZVPU7L.cjs} +23 -23
  11. package/dist/{chunk-4CPOKP27.js → chunk-QYXUE37Q.js} +1 -1
  12. package/dist/{chunk-MWUZCEFT.js → chunk-S2XPXA47.js} +1 -1
  13. package/dist/{chunk-EHLOCVWB.js → chunk-T2URHAJX.js} +27 -5
  14. package/dist/{chunk-FUDP5QBB.js → chunk-TNHDCP4R.js} +70 -3
  15. package/dist/{chunk-VBRHE4AM.cjs → chunk-U2ASNGO6.cjs} +35 -35
  16. package/dist/{chunk-THBJHPUL.js → chunk-YNFSH72F.js} +1 -1
  17. package/dist/effects/index.cjs +5 -2
  18. package/dist/effects/index.js +4 -1
  19. package/dist/effects/pool.d.cts +9 -0
  20. package/dist/effects/pool.d.ts +9 -0
  21. package/dist/effects/types.d.cts +2 -0
  22. package/dist/effects/types.d.ts +2 -0
  23. package/dist/image-editor/index.cjs +784 -784
  24. package/dist/image-editor/index.js +4 -4
  25. package/dist/paint-editor/controller.d.cts +75 -4
  26. package/dist/paint-editor/controller.d.ts +75 -4
  27. package/dist/paint-editor/effect-paint.d.cts +33 -8
  28. package/dist/paint-editor/effect-paint.d.ts +33 -8
  29. package/dist/paint-editor/effects.d.cts +4 -0
  30. package/dist/paint-editor/effects.d.ts +4 -0
  31. package/dist/paint-editor/index.cjs +692 -398
  32. package/dist/paint-editor/index.js +362 -68
  33. package/dist/paint-editor/stroke.d.cts +13 -5
  34. package/dist/paint-editor/stroke.d.ts +13 -5
  35. package/dist/vector/index.cjs +996 -996
  36. package/dist/vector/index.js +3 -3
  37. package/dist/video-editor/index.cjs +317 -317
  38. package/dist/video-editor/index.js +2 -2
  39. package/package.json +1 -1
  40. package/skills/pixerate-paint-editor/SKILL.md +2 -2
  41. package/skills/pixerate-paint-editor/references/effect-paint.md +28 -6
@@ -8,7 +8,7 @@ import {
8
8
  parseOpenTypeFont,
9
9
  removeAnchorsKeepingShape,
10
10
  traceField
11
- } from "../chunk-THBJHPUL.js";
11
+ } from "../chunk-YNFSH72F.js";
12
12
  import {
13
13
  ADJUSTMENT_KEYS,
14
14
  ADJUSTMENT_KINDS,
@@ -409,7 +409,7 @@ import {
409
409
  writePsd,
410
410
  xyToTempTint,
411
411
  xyToUv
412
- } from "../chunk-4YSPQGZW.js";
412
+ } from "../chunk-B5W677L7.js";
413
413
  import {
414
414
  flattenPath,
415
415
  rasterizeCoverage
@@ -683,7 +683,7 @@ import {
683
683
  warpMeshParamAt,
684
684
  warpMeshRows,
685
685
  warpPresetMesh
686
- } from "../chunk-FUDP5QBB.js";
686
+ } from "../chunk-TNHDCP4R.js";
687
687
  import {
688
688
  IMAGE_PROFILE,
689
689
  checkBrush,
@@ -706,7 +706,7 @@ import {
706
706
  import "../chunk-SZTI6EER.js";
707
707
  import {
708
708
  EffectRendererPool
709
- } from "../chunk-EHLOCVWB.js";
709
+ } from "../chunk-T2URHAJX.js";
710
710
  import {
711
711
  EffectUnsupportedError,
712
712
  EffectsSlot,
@@ -378,6 +378,17 @@ export declare class PaintEditorController {
378
378
  private paintEpoch;
379
379
  /** Rendered effect paints by `effectPaintKey` (most recently used last). */
380
380
  private readonly effectPaintPixels;
381
+ /** Primary path control name (`format: 'svg-path'`) per effect id, learned from `describeEffect`. */
382
+ private readonly effectPathControls;
383
+ /** How many renders the running batch needs together (`prepareEffectPaints`; a synchronous replay reads them all). */
384
+ private effectPaintBatch;
385
+ /** The hand-painted stroke waiting for its path render (`finishPathStroke`), or `null`. */
386
+ private pathStroke;
387
+ /**
388
+ * The hand-painted path stroke's live preview: the effect rendered along the path drawn so far
389
+ * (one render at a time; the newest path when it lands), repainted into the stroke as it lands.
390
+ */
391
+ private pathPreview;
381
392
  private mixerLoad;
382
393
  private view;
383
394
  private hand;
@@ -739,7 +750,11 @@ export declare class PaintEditorController {
739
750
  layerId: string;
740
751
  source: PaintEffectSource;
741
752
  }>;
742
- /** At most this many rendered effect paints are kept (each is canvas-sized). */
753
+ /**
754
+ * At most this many rendered effect paints are kept (each is canvas-sized), more only while
755
+ * something needs them all: a replay's batch, and the path-mapped strokes on stroke layers,
756
+ * which each have a render of their own and are redrawn synchronously.
757
+ */
743
758
  private static readonly EFFECT_PAINT_CACHE;
744
759
  /** The effect paint strokes use (or the one rendering), or `null`. */
745
760
  getEffectPaint(): PaintEffectPaint | null;
@@ -748,8 +763,10 @@ export declare class PaintEditorController {
748
763
  * size, and brushes then take each pixel's colour (and alpha) from it, fixed to the canvas, as if
749
764
  * painting a hidden picture into view. `setColor` and `setPaint` go back to colour. Editor state,
750
765
  * not an undo step. Strokes that would paint with it throw while it renders. Returns the paint.
751
- * With `map: { by: 'stroke' }` the effect lies along each stroke instead of the canvas; with
752
- * `live`, strokes on a stroke layer keep playing it (see `setEffectPlayback`).
766
+ * With `map: { by: 'stroke' }` the effect lies along each stroke as a strip; with
767
+ * `map: { by: 'path' }` an effect with a path control (`format: 'svg-path'`) draws itself along
768
+ * each stroke's centreline in canvas pixels; with `live`, strokes on a stroke layer keep playing
769
+ * it (see `setEffectPlayback`).
753
770
  */
754
771
  setEffectPaint(source: {
755
772
  effect: string;
@@ -760,15 +777,47 @@ export declare class PaintEditorController {
760
777
  }): Promise<PaintEffectPaint>;
761
778
  /** The rendered pixels of an effect paint at the current canvas size, or `null` when it has not been rendered. */
762
779
  private effectPaintImage;
780
+ private cacheEffectPaintPixels;
781
+ private cacheEffectPaintImage;
782
+ private trimEffectPaints;
783
+ /** Renders an effect paint on the caller's stack when its renderer is warm and has `renderSync`; otherwise `null`. */
784
+ private renderEffectPaintSync;
763
785
  /** Renders an effect paint at the canvas size into the cache (nothing when it is there already). */
764
786
  private renderEffectPaint;
787
+ /** Renders an effect paint at the canvas size without keeping it. */
788
+ private renderEffectPaintPixels;
765
789
  /**
766
790
  * Renders effect paints that are not rendered yet (strokes and replays need them rendered
767
791
  * first, since strokes are synchronous). Throws naming the effect and provider when one cannot be.
768
792
  */
769
793
  prepareEffectPaints(paints: Iterable<PaintEffectPaint>): Promise<void>;
794
+ /**
795
+ * Renders the path-mapped effect paint for one or more strokes' points before a synchronous
796
+ * stroke call runs (`paint_stroke` and `stroke_path` do; `paintStroke` throws without it on a
797
+ * provider that can't render synchronously). For a stroke layer edit, see `prepareStrokeEdit`.
798
+ */
799
+ prepareStrokePathEffect(init: PaintStrokeInit, pointsList: readonly (readonly PenPoint[])[]): Promise<void>;
800
+ /**
801
+ * Renders what an edit of a stroke layer's stroke paints with (`updateStroke`, `editStrokePoints`):
802
+ * a new effect paint, or a path-mapped stroke's new path. Those calls are synchronous, and throw
803
+ * without it on a provider that can't render synchronously. Bad edits are left for them to refuse.
804
+ */
805
+ prepareStrokeEdit(id: string, edit: {
806
+ paint?: unknown;
807
+ points?: readonly PenPoint[];
808
+ transform?: StrokeVariation;
809
+ }): Promise<void>;
810
+ /** Whether `prepareStrokeEdit` has to be awaited before this edit can run. */
811
+ strokeEditNeedsRender(id: string, edit: {
812
+ paint?: unknown;
813
+ points?: readonly PenPoint[];
814
+ transform?: StrokeVariation;
815
+ }): boolean;
816
+ private strokeEditPaint;
817
+ /** A stroke edit's transform as an affine map, checked. */
818
+ private strokeTransform;
770
819
  /** Renders the effect paints of recorded strokes (default all of them) before a replay. */
771
- prepareStrokeEffects(strokeIds?: readonly string[]): Promise<void>;
820
+ prepareStrokeEffects(strokeIds?: readonly string[], variation?: ReplayOptions): Promise<void>;
772
821
  /** A small preview of the effect paint (a PNG data URL `size` px wide), or `null` without a rendered one. */
773
822
  effectPaintThumbnail(size?: number): string | null;
774
823
  /**
@@ -945,8 +994,30 @@ export declare class PaintEditorController {
945
994
  * (one undo step) or `cancel()`.
946
995
  */
947
996
  beginStroke(init?: PaintStrokeInit): PaintStrokeSession;
997
+ /**
998
+ * Renders a hand-painted path stroke's effect along the path drawn so far and paints the stroke
999
+ * again with it when it lands, so the effect follows the pen while it draws. One render at a
1000
+ * time: when one lands, the next takes the newest path. A failed render leaves the preview as it
1001
+ * was; the render on release reports it.
1002
+ */
1003
+ private previewPathStroke;
948
1004
  /** The current live stroke, if any. */
949
1005
  get activeStroke(): PaintStrokeSession | null;
1006
+ /**
1007
+ * While a hand-painted stroke waits for its path render (`map: { by: 'path' }`), settles when it
1008
+ * has landed and rejects if it could not (the stroke is dropped); `null` otherwise. Until then
1009
+ * the editor is busy, as during a stroke, and shows the stroke as it was painted.
1010
+ */
1011
+ get strokeRendering(): Promise<void> | null;
1012
+ /** The paint a finished hand-painted stroke must be painted again with, or `null` when it already painted with it. */
1013
+ private pathStrokePaint;
1014
+ /**
1015
+ * Ends a hand-painted stroke with a path-mapped effect. Its whole path isn't known until now, so
1016
+ * the live stroke was only a preview from renders along the path so far (`previewPathStroke`):
1017
+ * nothing of it was committed. Paints it again with the path's own render, as one stroke and one undo step, at
1018
+ * once if that can render synchronously and when the render lands if not.
1019
+ */
1020
+ private finishPathStroke;
950
1021
  /** Runs a whole stroke against `doc` without touching the editor; returns the new document. */
951
1022
  private runStroke;
952
1023
  /** Paints one stroke from data (one undo step). */
@@ -378,6 +378,17 @@ export declare class PaintEditorController {
378
378
  private paintEpoch;
379
379
  /** Rendered effect paints by `effectPaintKey` (most recently used last). */
380
380
  private readonly effectPaintPixels;
381
+ /** Primary path control name (`format: 'svg-path'`) per effect id, learned from `describeEffect`. */
382
+ private readonly effectPathControls;
383
+ /** How many renders the running batch needs together (`prepareEffectPaints`; a synchronous replay reads them all). */
384
+ private effectPaintBatch;
385
+ /** The hand-painted stroke waiting for its path render (`finishPathStroke`), or `null`. */
386
+ private pathStroke;
387
+ /**
388
+ * The hand-painted path stroke's live preview: the effect rendered along the path drawn so far
389
+ * (one render at a time; the newest path when it lands), repainted into the stroke as it lands.
390
+ */
391
+ private pathPreview;
381
392
  private mixerLoad;
382
393
  private view;
383
394
  private hand;
@@ -739,7 +750,11 @@ export declare class PaintEditorController {
739
750
  layerId: string;
740
751
  source: PaintEffectSource;
741
752
  }>;
742
- /** At most this many rendered effect paints are kept (each is canvas-sized). */
753
+ /**
754
+ * At most this many rendered effect paints are kept (each is canvas-sized), more only while
755
+ * something needs them all: a replay's batch, and the path-mapped strokes on stroke layers,
756
+ * which each have a render of their own and are redrawn synchronously.
757
+ */
743
758
  private static readonly EFFECT_PAINT_CACHE;
744
759
  /** The effect paint strokes use (or the one rendering), or `null`. */
745
760
  getEffectPaint(): PaintEffectPaint | null;
@@ -748,8 +763,10 @@ export declare class PaintEditorController {
748
763
  * size, and brushes then take each pixel's colour (and alpha) from it, fixed to the canvas, as if
749
764
  * painting a hidden picture into view. `setColor` and `setPaint` go back to colour. Editor state,
750
765
  * not an undo step. Strokes that would paint with it throw while it renders. Returns the paint.
751
- * With `map: { by: 'stroke' }` the effect lies along each stroke instead of the canvas; with
752
- * `live`, strokes on a stroke layer keep playing it (see `setEffectPlayback`).
766
+ * With `map: { by: 'stroke' }` the effect lies along each stroke as a strip; with
767
+ * `map: { by: 'path' }` an effect with a path control (`format: 'svg-path'`) draws itself along
768
+ * each stroke's centreline in canvas pixels; with `live`, strokes on a stroke layer keep playing
769
+ * it (see `setEffectPlayback`).
753
770
  */
754
771
  setEffectPaint(source: {
755
772
  effect: string;
@@ -760,15 +777,47 @@ export declare class PaintEditorController {
760
777
  }): Promise<PaintEffectPaint>;
761
778
  /** The rendered pixels of an effect paint at the current canvas size, or `null` when it has not been rendered. */
762
779
  private effectPaintImage;
780
+ private cacheEffectPaintPixels;
781
+ private cacheEffectPaintImage;
782
+ private trimEffectPaints;
783
+ /** Renders an effect paint on the caller's stack when its renderer is warm and has `renderSync`; otherwise `null`. */
784
+ private renderEffectPaintSync;
763
785
  /** Renders an effect paint at the canvas size into the cache (nothing when it is there already). */
764
786
  private renderEffectPaint;
787
+ /** Renders an effect paint at the canvas size without keeping it. */
788
+ private renderEffectPaintPixels;
765
789
  /**
766
790
  * Renders effect paints that are not rendered yet (strokes and replays need them rendered
767
791
  * first, since strokes are synchronous). Throws naming the effect and provider when one cannot be.
768
792
  */
769
793
  prepareEffectPaints(paints: Iterable<PaintEffectPaint>): Promise<void>;
794
+ /**
795
+ * Renders the path-mapped effect paint for one or more strokes' points before a synchronous
796
+ * stroke call runs (`paint_stroke` and `stroke_path` do; `paintStroke` throws without it on a
797
+ * provider that can't render synchronously). For a stroke layer edit, see `prepareStrokeEdit`.
798
+ */
799
+ prepareStrokePathEffect(init: PaintStrokeInit, pointsList: readonly (readonly PenPoint[])[]): Promise<void>;
800
+ /**
801
+ * Renders what an edit of a stroke layer's stroke paints with (`updateStroke`, `editStrokePoints`):
802
+ * a new effect paint, or a path-mapped stroke's new path. Those calls are synchronous, and throw
803
+ * without it on a provider that can't render synchronously. Bad edits are left for them to refuse.
804
+ */
805
+ prepareStrokeEdit(id: string, edit: {
806
+ paint?: unknown;
807
+ points?: readonly PenPoint[];
808
+ transform?: StrokeVariation;
809
+ }): Promise<void>;
810
+ /** Whether `prepareStrokeEdit` has to be awaited before this edit can run. */
811
+ strokeEditNeedsRender(id: string, edit: {
812
+ paint?: unknown;
813
+ points?: readonly PenPoint[];
814
+ transform?: StrokeVariation;
815
+ }): boolean;
816
+ private strokeEditPaint;
817
+ /** A stroke edit's transform as an affine map, checked. */
818
+ private strokeTransform;
770
819
  /** Renders the effect paints of recorded strokes (default all of them) before a replay. */
771
- prepareStrokeEffects(strokeIds?: readonly string[]): Promise<void>;
820
+ prepareStrokeEffects(strokeIds?: readonly string[], variation?: ReplayOptions): Promise<void>;
772
821
  /** A small preview of the effect paint (a PNG data URL `size` px wide), or `null` without a rendered one. */
773
822
  effectPaintThumbnail(size?: number): string | null;
774
823
  /**
@@ -945,8 +994,30 @@ export declare class PaintEditorController {
945
994
  * (one undo step) or `cancel()`.
946
995
  */
947
996
  beginStroke(init?: PaintStrokeInit): PaintStrokeSession;
997
+ /**
998
+ * Renders a hand-painted path stroke's effect along the path drawn so far and paints the stroke
999
+ * again with it when it lands, so the effect follows the pen while it draws. One render at a
1000
+ * time: when one lands, the next takes the newest path. A failed render leaves the preview as it
1001
+ * was; the render on release reports it.
1002
+ */
1003
+ private previewPathStroke;
948
1004
  /** The current live stroke, if any. */
949
1005
  get activeStroke(): PaintStrokeSession | null;
1006
+ /**
1007
+ * While a hand-painted stroke waits for its path render (`map: { by: 'path' }`), settles when it
1008
+ * has landed and rejects if it could not (the stroke is dropped); `null` otherwise. Until then
1009
+ * the editor is busy, as during a stroke, and shows the stroke as it was painted.
1010
+ */
1011
+ get strokeRendering(): Promise<void> | null;
1012
+ /** The paint a finished hand-painted stroke must be painted again with, or `null` when it already painted with it. */
1013
+ private pathStrokePaint;
1014
+ /**
1015
+ * Ends a hand-painted stroke with a path-mapped effect. Its whole path isn't known until now, so
1016
+ * the live stroke was only a preview from renders along the path so far (`previewPathStroke`):
1017
+ * nothing of it was committed. Paints it again with the path's own render, as one stroke and one undo step, at
1018
+ * once if that can render synchronously and when the render lands if not.
1019
+ */
1020
+ private finishPathStroke;
950
1021
  /** Runs a whole stroke against `doc` without touching the editor; returns the new document. */
951
1022
  private runStroke;
952
1023
  /** Paints one stroke from data (one undo step). */
@@ -25,18 +25,19 @@ export interface PaintEffectPaint {
25
25
  /** Which moment of an animated effect, in ms. */
26
26
  time: number;
27
27
  /**
28
- * How the effect lies on the paint: fixed to the canvas (missing, the default), or along each
29
- * stroke (`by: 'stroke'`): the effect is rendered as a strip `length` px long and 256 px across,
30
- * and each pixel takes the colour at (distance along the stroke, position across the tip).
28
+ * How the effect lies on the paint: fixed to the canvas (missing, the default), bent along each
29
+ * stroke (`by: 'stroke'`: rendered as a strip `length` px long and 256 px across), or along the
30
+ * stroke via the effect's own path control (`by: 'path'`: the stroke's centreline in canvas
31
+ * pixels is passed to its `format: 'svg-path'` control).
31
32
  */
32
- map?: PaintEffectStrokeMap;
33
+ map?: PaintEffectMap;
33
34
  /**
34
35
  * Live: on a stroke layer the stroke keeps playing the effect (each frame drawn at the editor's
35
36
  * effect time); elsewhere it bakes the frame at `time` like any effect paint.
36
37
  */
37
38
  live?: boolean;
38
39
  }
39
- /** Effect paint laid along the stroke. */
40
+ /** Effect paint laid along the stroke as a bent strip. */
40
41
  export interface PaintEffectStrokeMap {
41
42
  by: 'stroke';
42
43
  /** Strip length: px of stroke per repeat of the effect, 16..4096. */
@@ -44,10 +45,34 @@ export interface PaintEffectStrokeMap {
44
45
  /** Past the strip's end: start again, run back (mirror), or hold the last colour (clamp). */
45
46
  repeat: 'repeat' | 'mirror' | 'clamp';
46
47
  }
48
+ /** Effect paint whose own path control (`format: 'svg-path'`) receives each stroke's centreline in canvas pixels. */
49
+ export interface PaintEffectPathMap {
50
+ by: 'path';
51
+ }
52
+ export type PaintEffectMap = PaintEffectStrokeMap | PaintEffectPathMap;
47
53
  /** How tall a stroke-mapped effect strip is rendered (the position across the tip maps onto it). */
48
54
  export declare const EFFECT_STRIP_HEIGHT = 256;
49
55
  export declare const EFFECT_MAP_REPEATS: readonly ["repeat", "mirror", "clamp"];
50
- /** The size an effect paint renders at: the canvas, or its strip. */
56
+ /** Maximum number of centreline points passed to a path effect control; longer strokes are resampled to this count. */
57
+ export declare const MAX_EFFECT_PATH_POINTS = 256;
58
+ /**
59
+ * The stroke's centreline as `[x0, y0, x1, y1, …]` in canvas pixels for a path control
60
+ * (`format: 'svg-path'`). Consecutive duplicate points are collapsed, single-point taps are doubled
61
+ * so path renderers receive a valid segment, and strokes longer than `maxPoints` are evenly
62
+ * resampled by arc length rather than refused.
63
+ */
64
+ export declare function strokePathPoints(points: readonly {
65
+ x: number;
66
+ y: number;
67
+ }[], maxPoints?: number): number[];
68
+ /** Which control of `values` holds a path when the effect description is not at hand. */
69
+ export declare function inferEffectPathControl(values: Record<string, EffectValue>): string;
70
+ /** A copy of a path-mapped effect paint with the stroke's centreline written into its path control. */
71
+ export declare function withStrokePath(paint: PaintEffectPaint, points: readonly {
72
+ x: number;
73
+ y: number;
74
+ }[], control?: string): PaintEffectPaint;
75
+ /** The size an effect paint renders at: the canvas, or its strip when bent along the stroke. */
51
76
  export declare function effectPaintSize(p: PaintEffectPaint, canvas: {
52
77
  width: number;
53
78
  height: number;
@@ -55,8 +80,8 @@ export declare function effectPaintSize(p: PaintEffectPaint, canvas: {
55
80
  width: number;
56
81
  height: number;
57
82
  };
58
- /** A stroke map checked and rounded; throws a sentence naming the bad field. */
59
- export declare function readEffectStrokeMap(raw: unknown): PaintEffectStrokeMap | undefined;
83
+ /** A stroke or path map checked and rounded; throws a sentence naming the bad field. */
84
+ export declare function readEffectStrokeMap(raw: unknown): PaintEffectMap | undefined;
60
85
  /**
61
86
  * Straight-alpha RGBA an effect paint was rendered to: canvas-sized, or (with `map`) the strip
62
87
  * laid along each stroke.
@@ -25,18 +25,19 @@ export interface PaintEffectPaint {
25
25
  /** Which moment of an animated effect, in ms. */
26
26
  time: number;
27
27
  /**
28
- * How the effect lies on the paint: fixed to the canvas (missing, the default), or along each
29
- * stroke (`by: 'stroke'`): the effect is rendered as a strip `length` px long and 256 px across,
30
- * and each pixel takes the colour at (distance along the stroke, position across the tip).
28
+ * How the effect lies on the paint: fixed to the canvas (missing, the default), bent along each
29
+ * stroke (`by: 'stroke'`: rendered as a strip `length` px long and 256 px across), or along the
30
+ * stroke via the effect's own path control (`by: 'path'`: the stroke's centreline in canvas
31
+ * pixels is passed to its `format: 'svg-path'` control).
31
32
  */
32
- map?: PaintEffectStrokeMap;
33
+ map?: PaintEffectMap;
33
34
  /**
34
35
  * Live: on a stroke layer the stroke keeps playing the effect (each frame drawn at the editor's
35
36
  * effect time); elsewhere it bakes the frame at `time` like any effect paint.
36
37
  */
37
38
  live?: boolean;
38
39
  }
39
- /** Effect paint laid along the stroke. */
40
+ /** Effect paint laid along the stroke as a bent strip. */
40
41
  export interface PaintEffectStrokeMap {
41
42
  by: 'stroke';
42
43
  /** Strip length: px of stroke per repeat of the effect, 16..4096. */
@@ -44,10 +45,34 @@ export interface PaintEffectStrokeMap {
44
45
  /** Past the strip's end: start again, run back (mirror), or hold the last colour (clamp). */
45
46
  repeat: 'repeat' | 'mirror' | 'clamp';
46
47
  }
48
+ /** Effect paint whose own path control (`format: 'svg-path'`) receives each stroke's centreline in canvas pixels. */
49
+ export interface PaintEffectPathMap {
50
+ by: 'path';
51
+ }
52
+ export type PaintEffectMap = PaintEffectStrokeMap | PaintEffectPathMap;
47
53
  /** How tall a stroke-mapped effect strip is rendered (the position across the tip maps onto it). */
48
54
  export declare const EFFECT_STRIP_HEIGHT = 256;
49
55
  export declare const EFFECT_MAP_REPEATS: readonly ["repeat", "mirror", "clamp"];
50
- /** The size an effect paint renders at: the canvas, or its strip. */
56
+ /** Maximum number of centreline points passed to a path effect control; longer strokes are resampled to this count. */
57
+ export declare const MAX_EFFECT_PATH_POINTS = 256;
58
+ /**
59
+ * The stroke's centreline as `[x0, y0, x1, y1, …]` in canvas pixels for a path control
60
+ * (`format: 'svg-path'`). Consecutive duplicate points are collapsed, single-point taps are doubled
61
+ * so path renderers receive a valid segment, and strokes longer than `maxPoints` are evenly
62
+ * resampled by arc length rather than refused.
63
+ */
64
+ export declare function strokePathPoints(points: readonly {
65
+ x: number;
66
+ y: number;
67
+ }[], maxPoints?: number): number[];
68
+ /** Which control of `values` holds a path when the effect description is not at hand. */
69
+ export declare function inferEffectPathControl(values: Record<string, EffectValue>): string;
70
+ /** A copy of a path-mapped effect paint with the stroke's centreline written into its path control. */
71
+ export declare function withStrokePath(paint: PaintEffectPaint, points: readonly {
72
+ x: number;
73
+ y: number;
74
+ }[], control?: string): PaintEffectPaint;
75
+ /** The size an effect paint renders at: the canvas, or its strip when bent along the stroke. */
51
76
  export declare function effectPaintSize(p: PaintEffectPaint, canvas: {
52
77
  width: number;
53
78
  height: number;
@@ -55,8 +80,8 @@ export declare function effectPaintSize(p: PaintEffectPaint, canvas: {
55
80
  width: number;
56
81
  height: number;
57
82
  };
58
- /** A stroke map checked and rounded; throws a sentence naming the bad field. */
59
- export declare function readEffectStrokeMap(raw: unknown): PaintEffectStrokeMap | undefined;
83
+ /** A stroke or path map checked and rounded; throws a sentence naming the bad field. */
84
+ export declare function readEffectStrokeMap(raw: unknown): PaintEffectMap | undefined;
60
85
  /**
61
86
  * Straight-alpha RGBA an effect paint was rendered to: canvas-sized, or (with `map`) the strip
62
87
  * laid along each stroke.
@@ -80,6 +80,10 @@ export declare class PaintEffectsRenderer {
80
80
  width: number;
81
81
  height: number;
82
82
  }, request: EffectRenderRequest): Promise<EffectPixels>;
83
+ renderSync(provider: EffectProvider, id: string, size: {
84
+ width: number;
85
+ height: number;
86
+ }, request: EffectRenderRequest): EffectPixels | null;
83
87
  dispose(): void;
84
88
  }
85
89
  /** A saved effect source, or `null` when it is not one. */
@@ -80,6 +80,10 @@ export declare class PaintEffectsRenderer {
80
80
  width: number;
81
81
  height: number;
82
82
  }, request: EffectRenderRequest): Promise<EffectPixels>;
83
+ renderSync(provider: EffectProvider, id: string, size: {
84
+ width: number;
85
+ height: number;
86
+ }, request: EffectRenderRequest): EffectPixels | null;
83
87
  dispose(): void;
84
88
  }
85
89
  /** A saved effect source, or `null` when it is not one. */