@pixerate/editor 0.272.0 → 0.273.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 (65) hide show
  1. package/dist/agent/index.cjs +34 -32
  2. package/dist/agent/index.js +10 -8
  3. package/dist/chart/contract.d.cts +95 -0
  4. package/dist/chart/contract.d.ts +95 -0
  5. package/dist/chart/controller.d.cts +4 -0
  6. package/dist/chart/controller.d.ts +4 -0
  7. package/dist/chart/index.cjs +492 -26
  8. package/dist/chart/index.d.cts +1 -0
  9. package/dist/chart/index.d.ts +1 -0
  10. package/dist/chart/index.js +476 -10
  11. package/dist/chart/tools.d.cts +3 -0
  12. package/dist/chart/tools.d.ts +3 -0
  13. package/dist/chart-maps/index.cjs +4 -64
  14. package/dist/chart-maps/index.js +3 -63
  15. package/dist/chunk-2A5IKZMU.js +557 -0
  16. package/dist/{chunk-NMZQMPFZ.js → chunk-4LZQO5Y7.js} +2 -0
  17. package/dist/chunk-5UGRMVNE.js +328 -0
  18. package/dist/{chunk-X4FTNFIA.js → chunk-7MGPW2OV.js} +1 -1
  19. package/dist/{chunk-DGITFN73.cjs → chunk-BWJBZAUE.cjs} +8 -8
  20. package/dist/chunk-CHZYVNXZ.js +336 -0
  21. package/dist/chunk-DRMZ5R3S.cjs +67 -0
  22. package/dist/chunk-EI5GFTKG.js +67 -0
  23. package/dist/chunk-JV7DKLMX.js +1073 -0
  24. package/dist/chunk-MFBUQC67.cjs +328 -0
  25. package/dist/{chunk-IBXEQOGI.js → chunk-PYHB2EHE.js} +2 -324
  26. package/dist/chunk-QEUI6OGE.cjs +336 -0
  27. package/dist/{chunk-6ZSFRRJI.js → chunk-RSF6BT34.js} +1 -1
  28. package/dist/chunk-T2HUQBRC.cjs +1073 -0
  29. package/dist/{chunk-GSLOH2IN.cjs → chunk-VF6ODSYX.cjs} +2 -0
  30. package/dist/{chunk-NQUKTRKN.cjs → chunk-WZLNNGG3.cjs} +45 -45
  31. package/dist/{chunk-NRBGAEFI.cjs → chunk-Y3RUYOOW.cjs} +8 -330
  32. package/dist/chunk-YH6SKC7P.cjs +557 -0
  33. package/dist/commands/index.cjs +7 -323
  34. package/dist/commands/index.js +5 -321
  35. package/dist/extensions/index.cjs +4 -4
  36. package/dist/extensions/index.js +3 -3
  37. package/dist/index.cjs +9 -9
  38. package/dist/index.js +3 -3
  39. package/dist/paint-editor/controller.d.cts +86 -0
  40. package/dist/paint-editor/controller.d.ts +86 -0
  41. package/dist/paint-editor/document.d.cts +1 -1
  42. package/dist/paint-editor/document.d.ts +1 -1
  43. package/dist/paint-editor/index.cjs +559 -166
  44. package/dist/paint-editor/index.d.cts +1 -0
  45. package/dist/paint-editor/index.d.ts +1 -0
  46. package/dist/paint-editor/index.js +397 -4
  47. package/dist/paint-editor/presence.d.cts +5 -1
  48. package/dist/paint-editor/presence.d.ts +5 -1
  49. package/dist/paint-editor/ui.d.cts +5 -2
  50. package/dist/paint-editor/ui.d.ts +5 -2
  51. package/dist/persistence/index.cjs +24 -1042
  52. package/dist/persistence/index.js +22 -1040
  53. package/dist/raster/fill.d.cts +85 -0
  54. package/dist/raster/fill.d.ts +85 -0
  55. package/dist/raster/index.cjs +9 -1
  56. package/dist/raster/index.d.cts +1 -0
  57. package/dist/raster/index.d.ts +1 -0
  58. package/dist/raster/index.js +8 -0
  59. package/dist/tools/index.cjs +5 -3
  60. package/dist/tools/index.js +8 -6
  61. package/package.json +1 -1
  62. package/skills/pixerate-paint-editor/SKILL.md +19 -43
  63. package/skills/pixerate-paint-editor/references/evolution.md +27 -0
  64. package/skills/pixerate-paint-sketch-to-finish/SKILL.md +16 -5
  65. package/skills/pixerate-paint-sketch-to-finish/evals/flats-under-ink.json +2 -3
@@ -0,0 +1,85 @@
1
+ import type { RasterRect } from './surface.cjs';
2
+ export interface FillRegionPoint {
3
+ x: number;
4
+ y: number;
5
+ }
6
+ export interface FillRegionSummary {
7
+ point: {
8
+ x: number;
9
+ y: number;
10
+ };
11
+ bounds: RasterRect | null;
12
+ pixelCount: number;
13
+ leaked: boolean;
14
+ }
15
+ export interface FillRegionMaskOptions {
16
+ /** Seed points in pixel coordinates. */
17
+ points: ReadonlyArray<FillRegionPoint>;
18
+ /** Per-channel RGBA tolerance 0..255 (default 32). */
19
+ tolerance?: number;
20
+ /** Close gaps in line art up to this width in pixels, 0..32 (default 0). */
21
+ closeGap?: number;
22
+ /** Expand (> 0, bleed under lines) or contract (< 0) the filled region in pixels, -16..16 (default 0). */
23
+ expand?: number;
24
+ /** Soften 1 px boundary edges (default true). */
25
+ antialias?: boolean;
26
+ }
27
+ export interface FillRegionMaskResult {
28
+ /** Per-pixel coverage 0..1 (`width * height`). */
29
+ mask: Float32Array;
30
+ /** Bounding box of all filled pixels, or null if nothing was filled. */
31
+ bounds: RasterRect | null;
32
+ /** Total number of filled pixels (`mask[i] > 0`). */
33
+ pixelCount: number;
34
+ /** True when the filled region touches the canvas edge (`x === 0`, `y === 0`, `x === width - 1`, or `y === height - 1`). */
35
+ leaked: boolean;
36
+ /** Per-seed summary in the order `points` were given. */
37
+ regions: FillRegionSummary[];
38
+ }
39
+ export interface UnfilledRegion {
40
+ /** Interior seed point guaranteed to lie inside the region (deepest interior point / pole of inaccessibility). */
41
+ point: {
42
+ x: number;
43
+ y: number;
44
+ };
45
+ /** Area-weighted centroid rounded to integer pixel coordinates. */
46
+ centroid: {
47
+ x: number;
48
+ y: number;
49
+ };
50
+ /** Tight bounding box of the region. */
51
+ bounds: RasterRect;
52
+ /** Area of the region in pixels. */
53
+ pixelCount: number;
54
+ /** True when the region touches the canvas edge. */
55
+ touchesEdge: boolean;
56
+ }
57
+ export interface FindUnfilledRegionsMaskOptions {
58
+ /** Optional target layer RGBA (`width * height * 4`). Pixels already painted on the target layer count as filled. */
59
+ target?: Uint8ClampedArray | Uint8Array;
60
+ /** Alpha/colour threshold 0..255 above which a reference pixel is treated as a barrier (default 32). */
61
+ tolerance?: number;
62
+ /** Close gaps in line art up to this width in pixels, 0..32 (default 0). */
63
+ closeGap?: number;
64
+ /** Ignore regions smaller than this many pixels (default 16). */
65
+ minArea?: number;
66
+ /** Include regions that touch the canvas border (default false: only enclosed shapes). */
67
+ includeEdge?: boolean;
68
+ /** Maximum number of regions to return, sorted largest first (default 100). */
69
+ maxRegions?: number;
70
+ }
71
+ /**
72
+ * Exact 2D squared Euclidean distance transform (Felzenszwalb & Huttenlocher, O(w * h)).
73
+ * Returns for each pixel the squared distance `(dx^2 + dy^2)` to the nearest `0` in `binary`.
74
+ */
75
+ export declare function squaredDistanceTransform(binary: Uint8Array, w: number, h: number): Float64Array;
76
+ /**
77
+ * Flood-fills one or more seed points against a reference RGBA buffer (`width * height * 4`),
78
+ * closing line-art gaps up to `closeGap` px and expanding/contracting the filled mask by `expand` px.
79
+ */
80
+ export declare function fillRegionMask(reference: Uint8ClampedArray | Uint8Array, width: number, height: number, options: FillRegionMaskOptions): FillRegionMaskResult;
81
+ /**
82
+ * Finds enclosed unfilled regions in a reference RGBA buffer (`width * height * 4`),
83
+ * closing gaps up to `closeGap` px and excluding areas already painted on `options.target`.
84
+ */
85
+ export declare function findUnfilledRegionsMask(reference: Uint8ClampedArray | Uint8Array, width: number, height: number, options?: FindUnfilledRegionsMaskOptions): UnfilledRegion[];
@@ -0,0 +1,85 @@
1
+ import type { RasterRect } from './surface.js';
2
+ export interface FillRegionPoint {
3
+ x: number;
4
+ y: number;
5
+ }
6
+ export interface FillRegionSummary {
7
+ point: {
8
+ x: number;
9
+ y: number;
10
+ };
11
+ bounds: RasterRect | null;
12
+ pixelCount: number;
13
+ leaked: boolean;
14
+ }
15
+ export interface FillRegionMaskOptions {
16
+ /** Seed points in pixel coordinates. */
17
+ points: ReadonlyArray<FillRegionPoint>;
18
+ /** Per-channel RGBA tolerance 0..255 (default 32). */
19
+ tolerance?: number;
20
+ /** Close gaps in line art up to this width in pixels, 0..32 (default 0). */
21
+ closeGap?: number;
22
+ /** Expand (> 0, bleed under lines) or contract (< 0) the filled region in pixels, -16..16 (default 0). */
23
+ expand?: number;
24
+ /** Soften 1 px boundary edges (default true). */
25
+ antialias?: boolean;
26
+ }
27
+ export interface FillRegionMaskResult {
28
+ /** Per-pixel coverage 0..1 (`width * height`). */
29
+ mask: Float32Array;
30
+ /** Bounding box of all filled pixels, or null if nothing was filled. */
31
+ bounds: RasterRect | null;
32
+ /** Total number of filled pixels (`mask[i] > 0`). */
33
+ pixelCount: number;
34
+ /** True when the filled region touches the canvas edge (`x === 0`, `y === 0`, `x === width - 1`, or `y === height - 1`). */
35
+ leaked: boolean;
36
+ /** Per-seed summary in the order `points` were given. */
37
+ regions: FillRegionSummary[];
38
+ }
39
+ export interface UnfilledRegion {
40
+ /** Interior seed point guaranteed to lie inside the region (deepest interior point / pole of inaccessibility). */
41
+ point: {
42
+ x: number;
43
+ y: number;
44
+ };
45
+ /** Area-weighted centroid rounded to integer pixel coordinates. */
46
+ centroid: {
47
+ x: number;
48
+ y: number;
49
+ };
50
+ /** Tight bounding box of the region. */
51
+ bounds: RasterRect;
52
+ /** Area of the region in pixels. */
53
+ pixelCount: number;
54
+ /** True when the region touches the canvas edge. */
55
+ touchesEdge: boolean;
56
+ }
57
+ export interface FindUnfilledRegionsMaskOptions {
58
+ /** Optional target layer RGBA (`width * height * 4`). Pixels already painted on the target layer count as filled. */
59
+ target?: Uint8ClampedArray | Uint8Array;
60
+ /** Alpha/colour threshold 0..255 above which a reference pixel is treated as a barrier (default 32). */
61
+ tolerance?: number;
62
+ /** Close gaps in line art up to this width in pixels, 0..32 (default 0). */
63
+ closeGap?: number;
64
+ /** Ignore regions smaller than this many pixels (default 16). */
65
+ minArea?: number;
66
+ /** Include regions that touch the canvas border (default false: only enclosed shapes). */
67
+ includeEdge?: boolean;
68
+ /** Maximum number of regions to return, sorted largest first (default 100). */
69
+ maxRegions?: number;
70
+ }
71
+ /**
72
+ * Exact 2D squared Euclidean distance transform (Felzenszwalb & Huttenlocher, O(w * h)).
73
+ * Returns for each pixel the squared distance `(dx^2 + dy^2)` to the nearest `0` in `binary`.
74
+ */
75
+ export declare function squaredDistanceTransform(binary: Uint8Array, w: number, h: number): Float64Array;
76
+ /**
77
+ * Flood-fills one or more seed points against a reference RGBA buffer (`width * height * 4`),
78
+ * closing line-art gaps up to `closeGap` px and expanding/contracting the filled mask by `expand` px.
79
+ */
80
+ export declare function fillRegionMask(reference: Uint8ClampedArray | Uint8Array, width: number, height: number, options: FillRegionMaskOptions): FillRegionMaskResult;
81
+ /**
82
+ * Finds enclosed unfilled regions in a reference RGBA buffer (`width * height * 4`),
83
+ * closing gaps up to `closeGap` px and excluding areas already painted on `options.target`.
84
+ */
85
+ export declare function findUnfilledRegionsMask(reference: Uint8ClampedArray | Uint8Array, width: number, height: number, options?: FindUnfilledRegionsMaskOptions): UnfilledRegion[];
@@ -2,6 +2,11 @@
2
2
 
3
3
 
4
4
 
5
+ var _chunkYH6SKC7Pcjs = require('../chunk-YH6SKC7P.cjs');
6
+
7
+
8
+
9
+
5
10
 
6
11
 
7
12
 
@@ -528,4 +533,7 @@ function drawSurfaceToViewport(ctx, surface, mapping, view, options) {
528
533
 
529
534
 
530
535
 
531
- exports.BIT_DEPTHS = _chunk2VX55NFMcjs.BIT_DEPTHS; exports.BLEND_MODES = _chunk2VX55NFMcjs.BLEND_MODES; exports.CURVE_LUT_SIZE = _chunkPVJMTLPJcjs.CURVE_LUT_SIZE; exports.DEFAULT_GLOBAL_LIGHT = _chunkPVJMTLPJcjs.DEFAULT_GLOBAL_LIGHT; exports.DIRECT_GAUSSIAN_MAX_SIGMA = _chunkK6PXS6DOcjs.DIRECT_GAUSSIAN_MAX_SIGMA; exports.DeepCompositor = _chunkPVJMTLPJcjs.DeepCompositor; exports.INTERPOLATIONS = _chunkPVJMTLPJcjs.INTERPOLATIONS; exports.LAYER_EFFECT_KINDS = _chunkPVJMTLPJcjs.LAYER_EFFECT_KINDS; exports.LAYER_EFFECT_MENU = _chunkPVJMTLPJcjs.LAYER_EFFECT_MENU; exports.LayerEffectError = _chunkPVJMTLPJcjs.LayerEffectError; exports.MAX_EFFECT_REACH = _chunkPVJMTLPJcjs.MAX_EFFECT_REACH; exports.MAX_TRANSFORM_PIXELS = _chunkPVJMTLPJcjs.MAX_TRANSFORM_PIXELS; exports.PAINTERLY_BLEND_MODES = _chunk2VX55NFMcjs.PAINTERLY_BLEND_MODES; exports.PatternPlacement = _chunkPVJMTLPJcjs.PatternPlacement; exports.PatternTile = _chunkPVJMTLPJcjs.PatternTile; exports.RasterCompositor = _chunkPVJMTLPJcjs.RasterCompositor; exports.SHADOW_AMBIENT = _chunk2VX55NFMcjs.SHADOW_AMBIENT; exports.STROKE_CHAMFER_MAX = _chunkPVJMTLPJcjs.STROKE_CHAMFER_MAX; exports.SurfaceDraft = _chunk474IQG74cjs.SurfaceDraft; exports.SurfaceViewportRenderer = SurfaceViewportRenderer; exports.TILE = _chunk474IQG74cjs.TILE; exports.TILE_SHIFT = _chunk474IQG74cjs.TILE_SHIFT; exports.TiledSurface = _chunk474IQG74cjs.TiledSurface; exports.TransformTooLargeError = _chunkPVJMTLPJcjs.TransformTooLargeError; exports.ZlibError = _chunkXFM3OCHUcjs.ZlibError; exports.activeEffectItems = _chunkPVJMTLPJcjs.activeEffectItems; exports.adler32 = _chunkXFM3OCHUcjs.adler32; exports.applyEdgeAmbient = _chunkPVJMTLPJcjs.applyEdgeAmbient; exports.base64ToBytes = _chunkW5M3J7PVcjs.base64ToBytes; exports.blendChannel = _chunk2VX55NFMcjs.blendChannel; exports.blendImageData = _chunk2VX55NFMcjs.blendImageData; exports.blendLum = _chunk2VX55NFMcjs.blendLum; exports.blendPixel = _chunk2VX55NFMcjs.blendPixel; exports.blendRgb = _chunk2VX55NFMcjs.blendRgb; exports.blendTile = _chunkPVJMTLPJcjs.blendTile; exports.buildEffectMaps = _chunkPVJMTLPJcjs.buildEffectMaps; exports.builtinPattern = _chunkPVJMTLPJcjs.builtinPattern; exports.builtinPatternIds = _chunkPVJMTLPJcjs.builtinPatternIds; exports.bytesToBase64 = _chunkW5M3J7PVcjs.bytesToBase64; exports.canvasCompositeOperation = _chunk2VX55NFMcjs.canvasCompositeOperation; exports.changedTiles = _chunkPVJMTLPJcjs.changedTiles; exports.collectTiles = _chunk474IQG74cjs.collectTiles; exports.compositeLayerEffects = _chunkPVJMTLPJcjs.compositeLayerEffects; exports.compositeSurfaceOver = _chunkPVJMTLPJcjs.compositeSurfaceOver; exports.contentBounds = _chunk474IQG74cjs.contentBounds; exports.contourLut = _chunkPVJMTLPJcjs.contourLut; exports.convertSurfaceDepth = _chunk2VX55NFMcjs.convertSurfaceDepth; exports.curveLut = _chunkPVJMTLPJcjs.curveLut; exports.decodePng = _chunkW5M3J7PVcjs.decodePng; exports.deepBytes = _chunk2VX55NFMcjs.deepBytes; exports.deepTile = _chunk2VX55NFMcjs.deepTile; exports.defaultEffectGradient = _chunkPVJMTLPJcjs.defaultEffectGradient; exports.defaultLayerEffect = _chunkPVJMTLPJcjs.defaultLayerEffect; exports.deflate = _chunkXFM3OCHUcjs.deflate; exports.deflateRaw = _chunkXFM3OCHUcjs.deflateRaw; exports.depthOf = _chunk2VX55NFMcjs.depthOf; exports.drawSurfaceToViewport = drawSurfaceToViewport; exports.effectColorHex = _chunkPVJMTLPJcjs.effectColorHex; exports.effectControlChange = _chunkPVJMTLPJcjs.effectControlChange; exports.effectFillColors = _chunkPVJMTLPJcjs.effectFillColors; exports.effectReach = _chunkPVJMTLPJcjs.effectReach; exports.effectsAreLocal = _chunkPVJMTLPJcjs.effectsAreLocal; exports.effectsFingerprint = _chunkPVJMTLPJcjs.effectsFingerprint; exports.effectsMargin = _chunkPVJMTLPJcjs.effectsMargin; exports.effectsScale = _chunkPVJMTLPJcjs.effectsScale; exports.emptySurface = _chunk474IQG74cjs.emptySurface; exports.encodePng = _chunkW5M3J7PVcjs.encodePng; exports.fillRect = _chunk474IQG74cjs.fillRect; exports.findLayer = _chunkPVJMTLPJcjs.findLayer; exports.finishTile = _chunk474IQG74cjs.finishTile; exports.flattenLayers = _chunkPVJMTLPJcjs.flattenLayers; exports.gaussianBlur = _chunkK6PXS6DOcjs.gaussianBlur; exports.gradientT = _chunkPVJMTLPJcjs.gradientT; exports.hasActiveEffects = _chunkPVJMTLPJcjs.hasActiveEffects; exports.hashNoise = _chunkPVJMTLPJcjs.hashNoise; exports.inflate = _chunkXFM3OCHUcjs.inflate; exports.inflateRaw = _chunkXFM3OCHUcjs.inflateRaw; exports.insertLayer = _chunkPVJMTLPJcjs.insertLayer; exports.isBitDepth = _chunk2VX55NFMcjs.isBitDepth; exports.isBlendMode = _chunk2VX55NFMcjs.isBlendMode; exports.isInterpolation = _chunkPVJMTLPJcjs.isInterpolation; exports.isLayerEffectKind = _chunkPVJMTLPJcjs.isLayerEffectKind; exports.isLayerLocked = _chunkPVJMTLPJcjs.isLayerLocked; exports.isPainterlyBlendMode = _chunk2VX55NFMcjs.isPainterlyBlendMode; exports.isPng = _chunkW5M3J7PVcjs.isPng; exports.isSeparableBlendMode = _chunk2VX55NFMcjs.isSeparableBlendMode; exports.keepDeepSamples = _chunk2VX55NFMcjs.keepDeepSamples; exports.keysWeight = _chunkPVJMTLPJcjs.keysWeight; exports.layerEffectControls = _chunkPVJMTLPJcjs.layerEffectControls; exports.layerEffectFields = _chunkPVJMTLPJcjs.layerEffectFields; exports.layerEffectLabel = _chunkPVJMTLPJcjs.layerEffectLabel; exports.layerEffectsBadge = _chunkPVJMTLPJcjs.layerEffectsBadge; exports.layerEffectsPanel = _chunkPVJMTLPJcjs.layerEffectsPanel; exports.mapLayer = _chunkPVJMTLPJcjs.mapLayer; exports.mergeLayerEffect = _chunkPVJMTLPJcjs.mergeLayerEffect; exports.mixPigment8 = _chunk2VX55NFMcjs.mixPigment8; exports.mixPigmentRgb = _chunk2VX55NFMcjs.mixPigmentRgb; exports.newEffectId = _chunkPVJMTLPJcjs.newEffectId; exports.normalizeBlendMode = _chunk2VX55NFMcjs.normalizeBlendMode; exports.normalizeLayerEffects = _chunkPVJMTLPJcjs.normalizeLayerEffects; exports.packRgba = _chunk474IQG74cjs.packRgba; exports.parseDataUrl = _chunkW5M3J7PVcjs.parseDataUrl; exports.parseEffectColor = _chunkPVJMTLPJcjs.parseEffectColor; exports.patchEffectMaps = _chunkPVJMTLPJcjs.patchEffectMaps; exports.pigment8 = _chunk2VX55NFMcjs.pigment8; exports.pngDataUrl = _chunkW5M3J7PVcjs.pngDataUrl; exports.proxyOf = _chunk2VX55NFMcjs.proxyOf; exports.readDeepRegion = _chunk2VX55NFMcjs.readDeepRegion; exports.readPixel = _chunk474IQG74cjs.readPixel; exports.readRegion = _chunk474IQG74cjs.readRegion; exports.reduceSurface = _chunkPVJMTLPJcjs.reduceSurface; exports.renderLayerEffects = _chunkPVJMTLPJcjs.renderLayerEffects; exports.scaleLayerEffect = _chunkPVJMTLPJcjs.scaleLayerEffect; exports.screenToWorld = screenToWorld; exports.setLum = _chunk2VX55NFMcjs.setLum; exports.solidSurface = _chunk474IQG74cjs.solidSurface; exports.srgbDecode = _chunk2VX55NFMcjs.srgbDecode; exports.srgbEncode = _chunk2VX55NFMcjs.srgbEncode; exports.standardBlendMode = _chunk2VX55NFMcjs.standardBlendMode; exports.surfaceBytes = _chunk474IQG74cjs.surfaceBytes; exports.surfaceDepth = _chunk2VX55NFMcjs.surfaceDepth; exports.surfaceFromDeepPixels = _chunk2VX55NFMcjs.surfaceFromDeepPixels; exports.surfaceFromPixels = _chunk474IQG74cjs.surfaceFromPixels; exports.surfaceMipLevel = surfaceMipLevel; exports.surfaceResolutionForZoom = surfaceResolutionForZoom; exports.surfaceToWorld = surfaceToWorld; exports.surfacesEqual = _chunk474IQG74cjs.surfacesEqual; exports.tileCoord = _chunk474IQG74cjs.tileCoord; exports.tileKey = _chunk474IQG74cjs.tileKey; exports.tileRect = _chunk474IQG74cjs.tileRect; exports.tileSamples = _chunk2VX55NFMcjs.tileSamples; exports.tileSamples16 = _chunk2VX55NFMcjs.tileSamples16; exports.tileSamples32 = _chunk2VX55NFMcjs.tileSamples32; exports.tilesInRect = _chunk474IQG74cjs.tilesInRect; exports.to16From32 = _chunk2VX55NFMcjs.to16From32; exports.to16From8 = _chunk2VX55NFMcjs.to16From8; exports.to32From16 = _chunk2VX55NFMcjs.to32From16; exports.to32From8 = _chunk2VX55NFMcjs.to32From8; exports.to8From16 = _chunk2VX55NFMcjs.to8From16; exports.to8From32 = _chunk2VX55NFMcjs.to8From32; exports.transformSurface = _chunkPVJMTLPJcjs.transformSurface; exports.transformedBounds = _chunkPVJMTLPJcjs.transformedBounds; exports.translateSurface = _chunk474IQG74cjs.translateSurface; exports.uniformTile = _chunk474IQG74cjs.uniformTile; exports.validateEffectGradient = _chunkPVJMTLPJcjs.validateEffectGradient; exports.validateLayerEffect = _chunkPVJMTLPJcjs.validateLayerEffect; exports.validateLayerEffects = _chunkPVJMTLPJcjs.validateLayerEffects; exports.visibleSurfaceRect = visibleSurfaceRect; exports.visibleWorldRect = visibleWorldRect; exports.warpSurface = _chunkPVJMTLPJcjs.warpSurface; exports.workingToSamples = _chunkPVJMTLPJcjs.workingToSamples; exports.worldRectToSurface = worldRectToSurface; exports.worldToSurface = worldToSurface; exports.writeDeepRegion = _chunk2VX55NFMcjs.writeDeepRegion; exports.writeRegion = _chunk474IQG74cjs.writeRegion;
536
+
537
+
538
+
539
+ exports.BIT_DEPTHS = _chunk2VX55NFMcjs.BIT_DEPTHS; exports.BLEND_MODES = _chunk2VX55NFMcjs.BLEND_MODES; exports.CURVE_LUT_SIZE = _chunkPVJMTLPJcjs.CURVE_LUT_SIZE; exports.DEFAULT_GLOBAL_LIGHT = _chunkPVJMTLPJcjs.DEFAULT_GLOBAL_LIGHT; exports.DIRECT_GAUSSIAN_MAX_SIGMA = _chunkK6PXS6DOcjs.DIRECT_GAUSSIAN_MAX_SIGMA; exports.DeepCompositor = _chunkPVJMTLPJcjs.DeepCompositor; exports.INTERPOLATIONS = _chunkPVJMTLPJcjs.INTERPOLATIONS; exports.LAYER_EFFECT_KINDS = _chunkPVJMTLPJcjs.LAYER_EFFECT_KINDS; exports.LAYER_EFFECT_MENU = _chunkPVJMTLPJcjs.LAYER_EFFECT_MENU; exports.LayerEffectError = _chunkPVJMTLPJcjs.LayerEffectError; exports.MAX_EFFECT_REACH = _chunkPVJMTLPJcjs.MAX_EFFECT_REACH; exports.MAX_TRANSFORM_PIXELS = _chunkPVJMTLPJcjs.MAX_TRANSFORM_PIXELS; exports.PAINTERLY_BLEND_MODES = _chunk2VX55NFMcjs.PAINTERLY_BLEND_MODES; exports.PatternPlacement = _chunkPVJMTLPJcjs.PatternPlacement; exports.PatternTile = _chunkPVJMTLPJcjs.PatternTile; exports.RasterCompositor = _chunkPVJMTLPJcjs.RasterCompositor; exports.SHADOW_AMBIENT = _chunk2VX55NFMcjs.SHADOW_AMBIENT; exports.STROKE_CHAMFER_MAX = _chunkPVJMTLPJcjs.STROKE_CHAMFER_MAX; exports.SurfaceDraft = _chunk474IQG74cjs.SurfaceDraft; exports.SurfaceViewportRenderer = SurfaceViewportRenderer; exports.TILE = _chunk474IQG74cjs.TILE; exports.TILE_SHIFT = _chunk474IQG74cjs.TILE_SHIFT; exports.TiledSurface = _chunk474IQG74cjs.TiledSurface; exports.TransformTooLargeError = _chunkPVJMTLPJcjs.TransformTooLargeError; exports.ZlibError = _chunkXFM3OCHUcjs.ZlibError; exports.activeEffectItems = _chunkPVJMTLPJcjs.activeEffectItems; exports.adler32 = _chunkXFM3OCHUcjs.adler32; exports.applyEdgeAmbient = _chunkPVJMTLPJcjs.applyEdgeAmbient; exports.base64ToBytes = _chunkW5M3J7PVcjs.base64ToBytes; exports.blendChannel = _chunk2VX55NFMcjs.blendChannel; exports.blendImageData = _chunk2VX55NFMcjs.blendImageData; exports.blendLum = _chunk2VX55NFMcjs.blendLum; exports.blendPixel = _chunk2VX55NFMcjs.blendPixel; exports.blendRgb = _chunk2VX55NFMcjs.blendRgb; exports.blendTile = _chunkPVJMTLPJcjs.blendTile; exports.buildEffectMaps = _chunkPVJMTLPJcjs.buildEffectMaps; exports.builtinPattern = _chunkPVJMTLPJcjs.builtinPattern; exports.builtinPatternIds = _chunkPVJMTLPJcjs.builtinPatternIds; exports.bytesToBase64 = _chunkW5M3J7PVcjs.bytesToBase64; exports.canvasCompositeOperation = _chunk2VX55NFMcjs.canvasCompositeOperation; exports.changedTiles = _chunkPVJMTLPJcjs.changedTiles; exports.collectTiles = _chunk474IQG74cjs.collectTiles; exports.compositeLayerEffects = _chunkPVJMTLPJcjs.compositeLayerEffects; exports.compositeSurfaceOver = _chunkPVJMTLPJcjs.compositeSurfaceOver; exports.contentBounds = _chunk474IQG74cjs.contentBounds; exports.contourLut = _chunkPVJMTLPJcjs.contourLut; exports.convertSurfaceDepth = _chunk2VX55NFMcjs.convertSurfaceDepth; exports.curveLut = _chunkPVJMTLPJcjs.curveLut; exports.decodePng = _chunkW5M3J7PVcjs.decodePng; exports.deepBytes = _chunk2VX55NFMcjs.deepBytes; exports.deepTile = _chunk2VX55NFMcjs.deepTile; exports.defaultEffectGradient = _chunkPVJMTLPJcjs.defaultEffectGradient; exports.defaultLayerEffect = _chunkPVJMTLPJcjs.defaultLayerEffect; exports.deflate = _chunkXFM3OCHUcjs.deflate; exports.deflateRaw = _chunkXFM3OCHUcjs.deflateRaw; exports.depthOf = _chunk2VX55NFMcjs.depthOf; exports.drawSurfaceToViewport = drawSurfaceToViewport; exports.effectColorHex = _chunkPVJMTLPJcjs.effectColorHex; exports.effectControlChange = _chunkPVJMTLPJcjs.effectControlChange; exports.effectFillColors = _chunkPVJMTLPJcjs.effectFillColors; exports.effectReach = _chunkPVJMTLPJcjs.effectReach; exports.effectsAreLocal = _chunkPVJMTLPJcjs.effectsAreLocal; exports.effectsFingerprint = _chunkPVJMTLPJcjs.effectsFingerprint; exports.effectsMargin = _chunkPVJMTLPJcjs.effectsMargin; exports.effectsScale = _chunkPVJMTLPJcjs.effectsScale; exports.emptySurface = _chunk474IQG74cjs.emptySurface; exports.encodePng = _chunkW5M3J7PVcjs.encodePng; exports.fillRect = _chunk474IQG74cjs.fillRect; exports.fillRegionMask = _chunkYH6SKC7Pcjs.fillRegionMask; exports.findLayer = _chunkPVJMTLPJcjs.findLayer; exports.findUnfilledRegionsMask = _chunkYH6SKC7Pcjs.findUnfilledRegionsMask; exports.finishTile = _chunk474IQG74cjs.finishTile; exports.flattenLayers = _chunkPVJMTLPJcjs.flattenLayers; exports.gaussianBlur = _chunkK6PXS6DOcjs.gaussianBlur; exports.gradientT = _chunkPVJMTLPJcjs.gradientT; exports.hasActiveEffects = _chunkPVJMTLPJcjs.hasActiveEffects; exports.hashNoise = _chunkPVJMTLPJcjs.hashNoise; exports.inflate = _chunkXFM3OCHUcjs.inflate; exports.inflateRaw = _chunkXFM3OCHUcjs.inflateRaw; exports.insertLayer = _chunkPVJMTLPJcjs.insertLayer; exports.isBitDepth = _chunk2VX55NFMcjs.isBitDepth; exports.isBlendMode = _chunk2VX55NFMcjs.isBlendMode; exports.isInterpolation = _chunkPVJMTLPJcjs.isInterpolation; exports.isLayerEffectKind = _chunkPVJMTLPJcjs.isLayerEffectKind; exports.isLayerLocked = _chunkPVJMTLPJcjs.isLayerLocked; exports.isPainterlyBlendMode = _chunk2VX55NFMcjs.isPainterlyBlendMode; exports.isPng = _chunkW5M3J7PVcjs.isPng; exports.isSeparableBlendMode = _chunk2VX55NFMcjs.isSeparableBlendMode; exports.keepDeepSamples = _chunk2VX55NFMcjs.keepDeepSamples; exports.keysWeight = _chunkPVJMTLPJcjs.keysWeight; exports.layerEffectControls = _chunkPVJMTLPJcjs.layerEffectControls; exports.layerEffectFields = _chunkPVJMTLPJcjs.layerEffectFields; exports.layerEffectLabel = _chunkPVJMTLPJcjs.layerEffectLabel; exports.layerEffectsBadge = _chunkPVJMTLPJcjs.layerEffectsBadge; exports.layerEffectsPanel = _chunkPVJMTLPJcjs.layerEffectsPanel; exports.mapLayer = _chunkPVJMTLPJcjs.mapLayer; exports.mergeLayerEffect = _chunkPVJMTLPJcjs.mergeLayerEffect; exports.mixPigment8 = _chunk2VX55NFMcjs.mixPigment8; exports.mixPigmentRgb = _chunk2VX55NFMcjs.mixPigmentRgb; exports.newEffectId = _chunkPVJMTLPJcjs.newEffectId; exports.normalizeBlendMode = _chunk2VX55NFMcjs.normalizeBlendMode; exports.normalizeLayerEffects = _chunkPVJMTLPJcjs.normalizeLayerEffects; exports.packRgba = _chunk474IQG74cjs.packRgba; exports.parseDataUrl = _chunkW5M3J7PVcjs.parseDataUrl; exports.parseEffectColor = _chunkPVJMTLPJcjs.parseEffectColor; exports.patchEffectMaps = _chunkPVJMTLPJcjs.patchEffectMaps; exports.pigment8 = _chunk2VX55NFMcjs.pigment8; exports.pngDataUrl = _chunkW5M3J7PVcjs.pngDataUrl; exports.proxyOf = _chunk2VX55NFMcjs.proxyOf; exports.readDeepRegion = _chunk2VX55NFMcjs.readDeepRegion; exports.readPixel = _chunk474IQG74cjs.readPixel; exports.readRegion = _chunk474IQG74cjs.readRegion; exports.reduceSurface = _chunkPVJMTLPJcjs.reduceSurface; exports.renderLayerEffects = _chunkPVJMTLPJcjs.renderLayerEffects; exports.scaleLayerEffect = _chunkPVJMTLPJcjs.scaleLayerEffect; exports.screenToWorld = screenToWorld; exports.setLum = _chunk2VX55NFMcjs.setLum; exports.solidSurface = _chunk474IQG74cjs.solidSurface; exports.squaredDistanceTransform = _chunkYH6SKC7Pcjs.squaredDistanceTransform; exports.srgbDecode = _chunk2VX55NFMcjs.srgbDecode; exports.srgbEncode = _chunk2VX55NFMcjs.srgbEncode; exports.standardBlendMode = _chunk2VX55NFMcjs.standardBlendMode; exports.surfaceBytes = _chunk474IQG74cjs.surfaceBytes; exports.surfaceDepth = _chunk2VX55NFMcjs.surfaceDepth; exports.surfaceFromDeepPixels = _chunk2VX55NFMcjs.surfaceFromDeepPixels; exports.surfaceFromPixels = _chunk474IQG74cjs.surfaceFromPixels; exports.surfaceMipLevel = surfaceMipLevel; exports.surfaceResolutionForZoom = surfaceResolutionForZoom; exports.surfaceToWorld = surfaceToWorld; exports.surfacesEqual = _chunk474IQG74cjs.surfacesEqual; exports.tileCoord = _chunk474IQG74cjs.tileCoord; exports.tileKey = _chunk474IQG74cjs.tileKey; exports.tileRect = _chunk474IQG74cjs.tileRect; exports.tileSamples = _chunk2VX55NFMcjs.tileSamples; exports.tileSamples16 = _chunk2VX55NFMcjs.tileSamples16; exports.tileSamples32 = _chunk2VX55NFMcjs.tileSamples32; exports.tilesInRect = _chunk474IQG74cjs.tilesInRect; exports.to16From32 = _chunk2VX55NFMcjs.to16From32; exports.to16From8 = _chunk2VX55NFMcjs.to16From8; exports.to32From16 = _chunk2VX55NFMcjs.to32From16; exports.to32From8 = _chunk2VX55NFMcjs.to32From8; exports.to8From16 = _chunk2VX55NFMcjs.to8From16; exports.to8From32 = _chunk2VX55NFMcjs.to8From32; exports.transformSurface = _chunkPVJMTLPJcjs.transformSurface; exports.transformedBounds = _chunkPVJMTLPJcjs.transformedBounds; exports.translateSurface = _chunk474IQG74cjs.translateSurface; exports.uniformTile = _chunk474IQG74cjs.uniformTile; exports.validateEffectGradient = _chunkPVJMTLPJcjs.validateEffectGradient; exports.validateLayerEffect = _chunkPVJMTLPJcjs.validateLayerEffect; exports.validateLayerEffects = _chunkPVJMTLPJcjs.validateLayerEffects; exports.visibleSurfaceRect = visibleSurfaceRect; exports.visibleWorldRect = visibleWorldRect; exports.warpSurface = _chunkPVJMTLPJcjs.warpSurface; exports.workingToSamples = _chunkPVJMTLPJcjs.workingToSamples; exports.worldRectToSurface = worldRectToSurface; exports.worldToSurface = worldToSurface; exports.writeDeepRegion = _chunk2VX55NFMcjs.writeDeepRegion; exports.writeRegion = _chunk474IQG74cjs.writeRegion;
@@ -23,3 +23,4 @@ export { activeEffectItems, buildEffectMaps, compositeLayerEffects, contourLut,
23
23
  export { encodePng, decodePng, isPng, bytesToBase64, base64ToBytes, parseDataUrl, pngDataUrl, type DecodedPng } from './png.cjs';
24
24
  export { inflate, inflateRaw, deflate, deflateRaw, adler32, ZlibError } from './zlib.cjs';
25
25
  export * from './viewport.cjs';
26
+ export * from './fill.cjs';
@@ -23,3 +23,4 @@ export { activeEffectItems, buildEffectMaps, compositeLayerEffects, contourLut,
23
23
  export { encodePng, decodePng, isPng, bytesToBase64, base64ToBytes, parseDataUrl, pngDataUrl, type DecodedPng } from './png.js';
24
24
  export { inflate, inflateRaw, deflate, deflateRaw, adler32, ZlibError } from './zlib.js';
25
25
  export * from './viewport.js';
26
+ export * from './fill.js';
@@ -1,3 +1,8 @@
1
+ import {
2
+ fillRegionMask,
3
+ findUnfilledRegionsMask,
4
+ squaredDistanceTransform
5
+ } from "../chunk-2A5IKZMU.js";
1
6
  import {
2
7
  CURVE_LUT_SIZE,
3
8
  DEFAULT_GLOBAL_LIGHT,
@@ -441,7 +446,9 @@ export {
441
446
  emptySurface,
442
447
  encodePng,
443
448
  fillRect,
449
+ fillRegionMask,
444
450
  findLayer,
451
+ findUnfilledRegionsMask,
445
452
  finishTile,
446
453
  flattenLayers,
447
454
  gaussianBlur,
@@ -489,6 +496,7 @@ export {
489
496
  screenToWorld,
490
497
  setLum,
491
498
  solidSurface,
499
+ squaredDistanceTransform,
492
500
  srgbDecode,
493
501
  srgbEncode,
494
502
  standardBlendMode,
@@ -18,21 +18,23 @@
18
18
 
19
19
 
20
20
 
21
+ var _chunkY3RUYOOWcjs = require('../chunk-Y3RUYOOW.cjs');
21
22
 
22
23
 
23
24
 
24
25
 
25
26
 
26
- var _chunkNRBGAEFIcjs = require('../chunk-NRBGAEFI.cjs');
27
27
 
28
28
 
29
29
 
30
+ var _chunkZEKI6EPIcjs = require('../chunk-ZEKI6EPI.cjs');
30
31
 
31
32
 
32
33
 
33
34
 
34
35
 
35
- var _chunkZEKI6EPIcjs = require('../chunk-ZEKI6EPI.cjs');
36
+
37
+ var _chunkMFBUQC67cjs = require('../chunk-MFBUQC67.cjs');
36
38
 
37
39
 
38
40
 
@@ -221,4 +223,4 @@ var _chunk2BSBFBOAcjs = require('../chunk-2BSBFBOA.cjs');
221
223
 
222
224
 
223
225
 
224
- exports.AgentPlayback = _chunk3SLBXKAWcjs.AgentPlayback; exports.CAPTURE_EXCLUDE_SELECTOR = _chunkSVFEVKLFcjs.CAPTURE_EXCLUDE_SELECTOR; exports.CAPTURE_OVERLAY_SELECTORS = _chunkSVFEVKLFcjs.CAPTURE_OVERLAY_SELECTORS; exports.CONFORMANCE_BINARY_MIN_LENGTH = _chunkNRBGAEFIcjs.CONFORMANCE_BINARY_MIN_LENGTH; exports.CONFORMANCE_NUMBER_TOLERANCE = _chunkNRBGAEFIcjs.CONFORMANCE_NUMBER_TOLERANCE; exports.ConformanceIds = _chunkNRBGAEFIcjs.ConformanceIds; exports.EDITOR_CANVAS_TOOLS = _chunkSVFEVKLFcjs.EDITOR_CANVAS_TOOLS; exports.EDITOR_MCP_TOOLS = _chunkSVFEVKLFcjs.EDITOR_MCP_TOOLS; exports.EDITOR_PROMPT_TOOLS = _chunkSVFEVKLFcjs.EDITOR_PROMPT_TOOLS; exports.EDIT_OPERATION_REQUIRED_ARGUMENTS = _chunkSVFEVKLFcjs.EDIT_OPERATION_REQUIRED_ARGUMENTS; exports.EXPORT_EXCLUDED_SELECTORS = _chunkSVFEVKLFcjs.EXPORT_EXCLUDED_SELECTORS; exports.JSON_RPC_ERRORS = _chunkZEKI6EPIcjs.JSON_RPC_ERRORS; exports.MCP_PROTOCOL_VERSIONS = _chunkZEKI6EPIcjs.MCP_PROTOCOL_VERSIONS; exports.MCP_TOOL_CANVAS_ADD_NODE = _chunkSVFEVKLFcjs.MCP_TOOL_CANVAS_ADD_NODE; exports.MCP_TOOL_CANVAS_CONNECT = _chunkSVFEVKLFcjs.MCP_TOOL_CANVAS_CONNECT; exports.MCP_TOOL_CANVAS_HIGHLIGHT = _chunkSVFEVKLFcjs.MCP_TOOL_CANVAS_HIGHLIGHT; exports.MCP_TOOL_CANVAS_LAYOUT = _chunkSVFEVKLFcjs.MCP_TOOL_CANVAS_LAYOUT; exports.MCP_TOOL_CANVAS_REMOVE_NODES = _chunkSVFEVKLFcjs.MCP_TOOL_CANVAS_REMOVE_NODES; exports.MCP_TOOL_CANVAS_SELECT = _chunkSVFEVKLFcjs.MCP_TOOL_CANVAS_SELECT; exports.MCP_TOOL_CANVAS_UPDATE_NODE = _chunkSVFEVKLFcjs.MCP_TOOL_CANVAS_UPDATE_NODE; exports.MCP_TOOL_EDIT_CANVAS = _chunkSVFEVKLFcjs.MCP_TOOL_EDIT_CANVAS; exports.MCP_TOOL_EDIT_PROMPT = _chunkSVFEVKLFcjs.MCP_TOOL_EDIT_PROMPT; exports.MCP_TOOL_GET_EDITOR_STATE = _chunkSVFEVKLFcjs.MCP_TOOL_GET_EDITOR_STATE; exports.MCP_TOOL_PROMPT_INSERT_TEXT = _chunkSVFEVKLFcjs.MCP_TOOL_PROMPT_INSERT_TEXT; exports.MCP_TOOL_PROMPT_REPLACE_RANGE = _chunkSVFEVKLFcjs.MCP_TOOL_PROMPT_REPLACE_RANGE; exports.MCP_TOOL_PROMPT_SELECT = _chunkSVFEVKLFcjs.MCP_TOOL_PROMPT_SELECT; exports.MCP_TOOL_PROMPT_SET_VARIABLE = _chunkSVFEVKLFcjs.MCP_TOOL_PROMPT_SET_VARIABLE; exports.MCP_TOOL_VIEW_EDITOR = _chunkSVFEVKLFcjs.MCP_TOOL_VIEW_EDITOR; exports.PRESENCE_COLORS = _chunkK7ENM55Pcjs.PRESENCE_COLORS; exports.PerformanceQueue = _chunkK7ENM55Pcjs.PerformanceQueue; exports.PresenceStore = _chunkK7ENM55Pcjs.PresenceStore; exports.TOOL_BRIDGE_DEFAULT_PORT = _chunkZEKI6EPIcjs.TOOL_BRIDGE_DEFAULT_PORT; exports.TOOL_BRIDGE_PROTOCOL = _chunkZEKI6EPIcjs.TOOL_BRIDGE_PROTOCOL; exports.TOOL_DISCOVERY_TOOLS = _chunk7TD63DZPcjs.TOOL_DISCOVERY_TOOLS; exports.TOOL_NAMESPACE_SEPARATOR = _chunk7TD63DZPcjs.TOOL_NAMESPACE_SEPARATOR; exports.ToolRegistry = _chunk7TD63DZPcjs.ToolRegistry; exports.ToolRegistryError = _chunk7TD63DZPcjs.ToolRegistryError; exports.ToolRegistryView = _chunk7TD63DZPcjs.ToolRegistryView; exports.UNSAFE_JSON_KEYS = _chunk2BSBFBOAcjs.UNSAFE_JSON_KEYS; exports.baseToolName = _chunk7TD63DZPcjs.baseToolName; exports.callEvalTool = _chunkNRBGAEFIcjs.callEvalTool; exports.captureInputSchema = _chunkN2FGYZ4Qcjs.captureInputSchema; exports.captureOutputSize = _chunkN2FGYZ4Qcjs.captureOutputSize; exports.cloneElementWithStyles = _chunkSVFEVKLFcjs.cloneElementWithStyles; exports.conformanceResult = _chunkNRBGAEFIcjs.conformanceResult; exports.conformanceValuesMatch = _chunkNRBGAEFIcjs.conformanceValuesMatch; exports.connectToolBridge = _chunkZEKI6EPIcjs.connectToolBridge; exports.createAgentPlayback = _chunk3SLBXKAWcjs.createAgentPlayback; exports.createCaptureTool = _chunkN2FGYZ4Qcjs.createCaptureTool; exports.createCaptureToolProvider = _chunkN2FGYZ4Qcjs.createCaptureToolProvider; exports.createElementCaptureSurface = _chunkSVFEVKLFcjs.createElementCaptureSurface; exports.createInstantPresenceClock = _chunkK7ENM55Pcjs.createInstantPresenceClock; exports.createMcpServer = _chunkZEKI6EPIcjs.createMcpServer; exports.createOriginMiddleware = _chunkNRBGAEFIcjs.createOriginMiddleware; exports.createPlaybackToolProvider = _chunk3SLBXKAWcjs.createPlaybackToolProvider; exports.createStyleResolver = _chunkNRBGAEFIcjs.createStyleResolver; exports.createStyleToolProvider = _chunkNRBGAEFIcjs.createStyleToolProvider; exports.createToolRegistry = _chunk7TD63DZPcjs.createToolRegistry; exports.derivePlaybackSteps = _chunk3SLBXKAWcjs.derivePlaybackSteps; exports.elementToSvg = _chunkSVFEVKLFcjs.elementToSvg; exports.errorResult = _chunk7TD63DZPcjs.errorResult; exports.failedEvalChecks = _chunkNRBGAEFIcjs.failedEvalChecks; exports.imageEvalFixturePixels = _chunkNRBGAEFIcjs.imageEvalFixturePixels; exports.isUnsafeJsonKey = _chunk2BSBFBOAcjs.isUnsafeJsonKey; exports.listSkillEvals = _chunkNRBGAEFIcjs.listSkillEvals; exports.listSkills = _chunk7TD63DZPcjs.listSkills; exports.locatePlaybackChrome = _chunk3SLBXKAWcjs.locatePlaybackChrome; exports.matchesEvalExpectation = _chunkNRBGAEFIcjs.matchesEvalExpectation; exports.memoryStyleStore = _chunkNRBGAEFIcjs.memoryStyleStore; exports.normalizeConformanceValue = _chunkNRBGAEFIcjs.normalizeConformanceValue; exports.omitConformancePaths = _chunkNRBGAEFIcjs.omitConformancePaths; exports.parseSkillFrontmatter = _chunk7TD63DZPcjs.parseSkillFrontmatter; exports.parseStyleDomains = _chunkNRBGAEFIcjs.parseStyleDomains; exports.playbackRectFromClient = _chunk3SLBXKAWcjs.playbackRectFromClient; exports.playbackRefsFromArgs = _chunk3SLBXKAWcjs.playbackRefsFromArgs; exports.playbackRefsFromResult = _chunk3SLBXKAWcjs.playbackRefsFromResult; exports.rasterizeElement = _chunkSVFEVKLFcjs.rasterizeElement; exports.readSkillFile = _chunk7TD63DZPcjs.readSkillFile; exports.readingTime = _chunk3SLBXKAWcjs.readingTime; exports.realPresenceClock = _chunkK7ENM55Pcjs.realPresenceClock; exports.renderStyle = _chunkNRBGAEFIcjs.renderStyle; exports.resolveCaptureRequest = _chunkN2FGYZ4Qcjs.resolveCaptureRequest; exports.resolveConformanceArguments = _chunkNRBGAEFIcjs.resolveConformanceArguments; exports.runConformanceScenario = _chunkNRBGAEFIcjs.runConformanceScenario; exports.runStyleChecks = _chunkNRBGAEFIcjs.runStyleChecks; exports.runToolScript = _chunkNRBGAEFIcjs.runToolScript; exports.searchTokens = _chunk7TD63DZPcjs.searchTokens; exports.searchTools = _chunk7TD63DZPcjs.searchTools; exports.stripPrototypeKeys = _chunk2BSBFBOAcjs.stripPrototypeKeys; exports.summarize = _chunk7TD63DZPcjs.summarize; exports.toCapturedImageData = _chunkN2FGYZ4Qcjs.toCapturedImageData; exports.toToolResult = _chunk7TD63DZPcjs.toToolResult; exports.toolResultError = _chunkNRBGAEFIcjs.toolResultError; exports.toolResultValue = _chunkNRBGAEFIcjs.toolResultValue; exports.toolsetInstructions = _chunkZEKI6EPIcjs.toolsetInstructions; exports.toolsetName = _chunk7TD63DZPcjs.toolsetName; exports.trackPresenceDrag = _chunkK7ENM55Pcjs.trackPresenceDrag; exports.tweenPresenceCursor = _chunkK7ENM55Pcjs.tweenPresenceCursor; exports.unionCaptureRects = _chunkN2FGYZ4Qcjs.unionCaptureRects; exports.unionRects = _chunk3SLBXKAWcjs.unionRects; exports.unknownToolMessage = _chunk7TD63DZPcjs.unknownToolMessage; exports.validateJsonSchema = _chunkWOFXZ3XUcjs.validateJsonSchema;
226
+ exports.AgentPlayback = _chunk3SLBXKAWcjs.AgentPlayback; exports.CAPTURE_EXCLUDE_SELECTOR = _chunkSVFEVKLFcjs.CAPTURE_EXCLUDE_SELECTOR; exports.CAPTURE_OVERLAY_SELECTORS = _chunkSVFEVKLFcjs.CAPTURE_OVERLAY_SELECTORS; exports.CONFORMANCE_BINARY_MIN_LENGTH = _chunkY3RUYOOWcjs.CONFORMANCE_BINARY_MIN_LENGTH; exports.CONFORMANCE_NUMBER_TOLERANCE = _chunkY3RUYOOWcjs.CONFORMANCE_NUMBER_TOLERANCE; exports.ConformanceIds = _chunkY3RUYOOWcjs.ConformanceIds; exports.EDITOR_CANVAS_TOOLS = _chunkSVFEVKLFcjs.EDITOR_CANVAS_TOOLS; exports.EDITOR_MCP_TOOLS = _chunkSVFEVKLFcjs.EDITOR_MCP_TOOLS; exports.EDITOR_PROMPT_TOOLS = _chunkSVFEVKLFcjs.EDITOR_PROMPT_TOOLS; exports.EDIT_OPERATION_REQUIRED_ARGUMENTS = _chunkSVFEVKLFcjs.EDIT_OPERATION_REQUIRED_ARGUMENTS; exports.EXPORT_EXCLUDED_SELECTORS = _chunkSVFEVKLFcjs.EXPORT_EXCLUDED_SELECTORS; exports.JSON_RPC_ERRORS = _chunkZEKI6EPIcjs.JSON_RPC_ERRORS; exports.MCP_PROTOCOL_VERSIONS = _chunkZEKI6EPIcjs.MCP_PROTOCOL_VERSIONS; exports.MCP_TOOL_CANVAS_ADD_NODE = _chunkSVFEVKLFcjs.MCP_TOOL_CANVAS_ADD_NODE; exports.MCP_TOOL_CANVAS_CONNECT = _chunkSVFEVKLFcjs.MCP_TOOL_CANVAS_CONNECT; exports.MCP_TOOL_CANVAS_HIGHLIGHT = _chunkSVFEVKLFcjs.MCP_TOOL_CANVAS_HIGHLIGHT; exports.MCP_TOOL_CANVAS_LAYOUT = _chunkSVFEVKLFcjs.MCP_TOOL_CANVAS_LAYOUT; exports.MCP_TOOL_CANVAS_REMOVE_NODES = _chunkSVFEVKLFcjs.MCP_TOOL_CANVAS_REMOVE_NODES; exports.MCP_TOOL_CANVAS_SELECT = _chunkSVFEVKLFcjs.MCP_TOOL_CANVAS_SELECT; exports.MCP_TOOL_CANVAS_UPDATE_NODE = _chunkSVFEVKLFcjs.MCP_TOOL_CANVAS_UPDATE_NODE; exports.MCP_TOOL_EDIT_CANVAS = _chunkSVFEVKLFcjs.MCP_TOOL_EDIT_CANVAS; exports.MCP_TOOL_EDIT_PROMPT = _chunkSVFEVKLFcjs.MCP_TOOL_EDIT_PROMPT; exports.MCP_TOOL_GET_EDITOR_STATE = _chunkSVFEVKLFcjs.MCP_TOOL_GET_EDITOR_STATE; exports.MCP_TOOL_PROMPT_INSERT_TEXT = _chunkSVFEVKLFcjs.MCP_TOOL_PROMPT_INSERT_TEXT; exports.MCP_TOOL_PROMPT_REPLACE_RANGE = _chunkSVFEVKLFcjs.MCP_TOOL_PROMPT_REPLACE_RANGE; exports.MCP_TOOL_PROMPT_SELECT = _chunkSVFEVKLFcjs.MCP_TOOL_PROMPT_SELECT; exports.MCP_TOOL_PROMPT_SET_VARIABLE = _chunkSVFEVKLFcjs.MCP_TOOL_PROMPT_SET_VARIABLE; exports.MCP_TOOL_VIEW_EDITOR = _chunkSVFEVKLFcjs.MCP_TOOL_VIEW_EDITOR; exports.PRESENCE_COLORS = _chunkK7ENM55Pcjs.PRESENCE_COLORS; exports.PerformanceQueue = _chunkK7ENM55Pcjs.PerformanceQueue; exports.PresenceStore = _chunkK7ENM55Pcjs.PresenceStore; exports.TOOL_BRIDGE_DEFAULT_PORT = _chunkZEKI6EPIcjs.TOOL_BRIDGE_DEFAULT_PORT; exports.TOOL_BRIDGE_PROTOCOL = _chunkZEKI6EPIcjs.TOOL_BRIDGE_PROTOCOL; exports.TOOL_DISCOVERY_TOOLS = _chunk7TD63DZPcjs.TOOL_DISCOVERY_TOOLS; exports.TOOL_NAMESPACE_SEPARATOR = _chunk7TD63DZPcjs.TOOL_NAMESPACE_SEPARATOR; exports.ToolRegistry = _chunk7TD63DZPcjs.ToolRegistry; exports.ToolRegistryError = _chunk7TD63DZPcjs.ToolRegistryError; exports.ToolRegistryView = _chunk7TD63DZPcjs.ToolRegistryView; exports.UNSAFE_JSON_KEYS = _chunk2BSBFBOAcjs.UNSAFE_JSON_KEYS; exports.baseToolName = _chunk7TD63DZPcjs.baseToolName; exports.callEvalTool = _chunkY3RUYOOWcjs.callEvalTool; exports.captureInputSchema = _chunkN2FGYZ4Qcjs.captureInputSchema; exports.captureOutputSize = _chunkN2FGYZ4Qcjs.captureOutputSize; exports.cloneElementWithStyles = _chunkSVFEVKLFcjs.cloneElementWithStyles; exports.conformanceResult = _chunkY3RUYOOWcjs.conformanceResult; exports.conformanceValuesMatch = _chunkY3RUYOOWcjs.conformanceValuesMatch; exports.connectToolBridge = _chunkZEKI6EPIcjs.connectToolBridge; exports.createAgentPlayback = _chunk3SLBXKAWcjs.createAgentPlayback; exports.createCaptureTool = _chunkN2FGYZ4Qcjs.createCaptureTool; exports.createCaptureToolProvider = _chunkN2FGYZ4Qcjs.createCaptureToolProvider; exports.createElementCaptureSurface = _chunkSVFEVKLFcjs.createElementCaptureSurface; exports.createInstantPresenceClock = _chunkK7ENM55Pcjs.createInstantPresenceClock; exports.createMcpServer = _chunkZEKI6EPIcjs.createMcpServer; exports.createOriginMiddleware = _chunkY3RUYOOWcjs.createOriginMiddleware; exports.createPlaybackToolProvider = _chunk3SLBXKAWcjs.createPlaybackToolProvider; exports.createStyleResolver = _chunkMFBUQC67cjs.createStyleResolver; exports.createStyleToolProvider = _chunkY3RUYOOWcjs.createStyleToolProvider; exports.createToolRegistry = _chunk7TD63DZPcjs.createToolRegistry; exports.derivePlaybackSteps = _chunk3SLBXKAWcjs.derivePlaybackSteps; exports.elementToSvg = _chunkSVFEVKLFcjs.elementToSvg; exports.errorResult = _chunk7TD63DZPcjs.errorResult; exports.failedEvalChecks = _chunkY3RUYOOWcjs.failedEvalChecks; exports.imageEvalFixturePixels = _chunkY3RUYOOWcjs.imageEvalFixturePixels; exports.isUnsafeJsonKey = _chunk2BSBFBOAcjs.isUnsafeJsonKey; exports.listSkillEvals = _chunkY3RUYOOWcjs.listSkillEvals; exports.listSkills = _chunk7TD63DZPcjs.listSkills; exports.locatePlaybackChrome = _chunk3SLBXKAWcjs.locatePlaybackChrome; exports.matchesEvalExpectation = _chunkY3RUYOOWcjs.matchesEvalExpectation; exports.memoryStyleStore = _chunkMFBUQC67cjs.memoryStyleStore; exports.normalizeConformanceValue = _chunkY3RUYOOWcjs.normalizeConformanceValue; exports.omitConformancePaths = _chunkY3RUYOOWcjs.omitConformancePaths; exports.parseSkillFrontmatter = _chunk7TD63DZPcjs.parseSkillFrontmatter; exports.parseStyleDomains = _chunkMFBUQC67cjs.parseStyleDomains; exports.playbackRectFromClient = _chunk3SLBXKAWcjs.playbackRectFromClient; exports.playbackRefsFromArgs = _chunk3SLBXKAWcjs.playbackRefsFromArgs; exports.playbackRefsFromResult = _chunk3SLBXKAWcjs.playbackRefsFromResult; exports.rasterizeElement = _chunkSVFEVKLFcjs.rasterizeElement; exports.readSkillFile = _chunk7TD63DZPcjs.readSkillFile; exports.readingTime = _chunk3SLBXKAWcjs.readingTime; exports.realPresenceClock = _chunkK7ENM55Pcjs.realPresenceClock; exports.renderStyle = _chunkMFBUQC67cjs.renderStyle; exports.resolveCaptureRequest = _chunkN2FGYZ4Qcjs.resolveCaptureRequest; exports.resolveConformanceArguments = _chunkY3RUYOOWcjs.resolveConformanceArguments; exports.runConformanceScenario = _chunkY3RUYOOWcjs.runConformanceScenario; exports.runStyleChecks = _chunkMFBUQC67cjs.runStyleChecks; exports.runToolScript = _chunkY3RUYOOWcjs.runToolScript; exports.searchTokens = _chunk7TD63DZPcjs.searchTokens; exports.searchTools = _chunk7TD63DZPcjs.searchTools; exports.stripPrototypeKeys = _chunk2BSBFBOAcjs.stripPrototypeKeys; exports.summarize = _chunk7TD63DZPcjs.summarize; exports.toCapturedImageData = _chunkN2FGYZ4Qcjs.toCapturedImageData; exports.toToolResult = _chunk7TD63DZPcjs.toToolResult; exports.toolResultError = _chunkY3RUYOOWcjs.toolResultError; exports.toolResultValue = _chunkY3RUYOOWcjs.toolResultValue; exports.toolsetInstructions = _chunkZEKI6EPIcjs.toolsetInstructions; exports.toolsetName = _chunk7TD63DZPcjs.toolsetName; exports.trackPresenceDrag = _chunkK7ENM55Pcjs.trackPresenceDrag; exports.tweenPresenceCursor = _chunkK7ENM55Pcjs.tweenPresenceCursor; exports.unionCaptureRects = _chunkN2FGYZ4Qcjs.unionCaptureRects; exports.unionRects = _chunk3SLBXKAWcjs.unionRects; exports.unknownToolMessage = _chunk7TD63DZPcjs.unknownToolMessage; exports.validateJsonSchema = _chunkWOFXZ3XUcjs.validateJsonSchema;
@@ -6,24 +6,19 @@ import {
6
6
  conformanceResult,
7
7
  conformanceValuesMatch,
8
8
  createOriginMiddleware,
9
- createStyleResolver,
10
9
  createStyleToolProvider,
11
10
  failedEvalChecks,
12
11
  imageEvalFixturePixels,
13
12
  listSkillEvals,
14
13
  matchesEvalExpectation,
15
- memoryStyleStore,
16
14
  normalizeConformanceValue,
17
15
  omitConformancePaths,
18
- parseStyleDomains,
19
- renderStyle,
20
16
  resolveConformanceArguments,
21
17
  runConformanceScenario,
22
- runStyleChecks,
23
18
  runToolScript,
24
19
  toolResultError,
25
20
  toolResultValue
26
- } from "../chunk-IBXEQOGI.js";
21
+ } from "../chunk-PYHB2EHE.js";
27
22
  import {
28
23
  JSON_RPC_ERRORS,
29
24
  MCP_PROTOCOL_VERSIONS,
@@ -33,6 +28,13 @@ import {
33
28
  createMcpServer,
34
29
  toolsetInstructions
35
30
  } from "../chunk-SYEOA5MS.js";
31
+ import {
32
+ createStyleResolver,
33
+ memoryStyleStore,
34
+ parseStyleDomains,
35
+ renderStyle,
36
+ runStyleChecks
37
+ } from "../chunk-5UGRMVNE.js";
36
38
  import {
37
39
  TOOL_DISCOVERY_TOOLS,
38
40
  TOOL_NAMESPACE_SEPARATOR,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pixerate/editor",
3
- "version": "0.272.0",
3
+ "version": "0.273.0",
4
4
  "description": "UI-agnostic rich text and media editing core library",
5
5
  "author": "Pixerate",
6
6
  "license": "MIT",
@@ -77,36 +77,14 @@ the pitfalls, and uses the tools below.
77
77
  `new_canvas` with `paper`): cold pressed or rough for broken, sparkling texture, sanded pastel
78
78
  paper for pastel, charcoal paper for charcoal, cotton canvas or gesso for painterly work,
79
79
  smooth bristol for ink. Set `depth` for how much texture you want.
80
- 3. **Block in big shapes first.** Put each pass on its own layer (`add_layer` with a name).
81
- `fill_layer` gives a ground colour (flat) or a tonal layer that catches the grain
82
- (`grain` 0.6..1, `pressure` 0.2..0.6). Paint large masses with a big soft pastel or airbrush
83
- in a few long `paint_stroke`s rather than many small ones.
84
- 4. **Plan and mix colours before painting.** `color_harmony` gives a palette around a key colour
85
- (on the painter's red-yellow-blue wheel by default). `mix_colors` predicts what paints mixed
86
- in given parts look like (Kubelka-Munk: blue and yellow make green, white tints rather than
87
- greys); the mixing pad (`mixing_pad_stroke`, `pick_mixing_pad_color`) mixes by hand with a
88
- palette knife. Keep chosen colours as swatches (`add_swatch`). Use the result as the stroke
89
- `color`; `set_color` makes it the default.
90
- 5. **Refine** with smaller brushes on new layers: pencil and ink for line, charcoal for value.
91
- **Blend** on the layer that holds the paint: `blender` to melt neighbouring colours together
92
- (pigment mixing, so blue next to yellow goes green), `smudge` / `wet-smudge` to drag paint
93
- into soft edges and streaks, `mixer-brush` to paint wet into wet, `dirty-round` to paint with
94
- a brush that picks up and carries colour, `multicolor-flat` for strokes loaded with several
95
- colours. Glaze with a `watercolor` layer, warm or cool with `tint`, light with `highlight`,
96
- shade with `shadow`.
97
- 6. **Let the guides multiply your marks.** `set_symmetry` (mirror for faces and vases,
98
- kaleidoscope for mandalas and ornaments) paints every copy from one stroke;
99
- `set_perspective_guide` plus `paint_stroke` with `snapToPerspective` lays converging lines for
100
- buildings and roads. To copy an image's composition and colours, `set_tracing_image` with
101
- `sampleColors` and paint over it.
102
- 7. **Repeat and vary instead of drawing every mark.** Paint one good stroke, then
103
- `replay_strokes` it with `dx` / `dy`, `rotate`, `scale`, `flipX`, `color`, `brushId` and
104
- `repeat` for hatching, grass, foliage, rows, fans or spirals, in one undo step.
105
- 8. **Check** with `render_preview` after each block of work, not after each stroke.
106
- `pick_color` reads exact values. Undo what made it worse.
80
+ 3. **Block in big shapes first.** Put each pass on its own layer (`add_layer` with a name). `fill_layer` gives a ground colour (flat) or a tonal layer that catches the grain (`grain` 0.6..1, `pressure` 0.2..0.6). For line art, call `find_unfilled_regions` against the ink layer (`reference: inkLayerId`, `closeGap: 4..8`) to list enclosed shapes and their interior seed points, then `fill_region` on a flats layer below the ink (`reference: inkLayerId`, `closeGap: 4..8`, `expand: 1..2` so no halo shows at anti-aliased line edges, or `wet: true` to pour a watercolour wash into the region). For unoutlined masses, paint with a big soft pastel or airbrush in a few long `paint_stroke`s rather than many small ones.
81
+ 4. **Plan and mix colours before painting.** `color_harmony` gives a palette around a key colour (on the painter's red-yellow-blue wheel by default). `mix_colors` predicts what paints mixed in given parts look like (Kubelka-Munk: blue and yellow make green, white tints rather than greys); the mixing pad (`mixing_pad_stroke`, `pick_mixing_pad_color`) mixes by hand with a palette knife. Keep chosen colours as swatches (`add_swatch`). Use the result as the stroke `color`; `set_color` makes it the default.
82
+ 5. **Refine** with smaller brushes on new layers: pencil and ink for line, charcoal for value. **Blend** on the layer that holds the paint: `blender` to melt neighbouring colours together (pigment mixing, so blue next to yellow goes green), `smudge` / `wet-smudge` to drag paint into soft edges and streaks, `mixer-brush` to paint wet into wet, `dirty-round` to paint with a brush that picks up and carries colour, `multicolor-flat` for strokes loaded with several colours. Glaze with a `watercolor` layer, warm or cool with `tint`, light with `highlight`, shade with `shadow`.
83
+ 6. **Let the guides multiply your marks.** `set_symmetry` (mirror for faces and vases, kaleidoscope for mandalas and ornaments) paints every copy from one stroke; `set_perspective_guide` plus `paint_stroke` with `snapToPerspective` lays converging lines for buildings and roads. To copy an image's composition and colours, `set_tracing_image` with `sampleColors` and paint over it.
84
+ 7. **Repeat and vary instead of drawing every mark.** Paint one good stroke, then `replay_strokes` it with `dx` / `dy`, `rotate`, `scale`, `flipX`, `color`, `brushId` and `repeat` for hatching, grass, foliage, rows, fans or spirals, in one undo step.
85
+ 8. **Check** with `render_preview` after each block of work, not after each stroke. `pick_color` reads exact values. Undo what made it worse.
107
86
  9. **Watercolour** is its own way of working: see "Wet media" below.
108
- 10. **Deliver**: `export_image` (PNG, or JPEG / WebP in a browser), `export_psd` for Photoshop,
109
- `save_paint_document` to keep the painting with its strokes (when the host has storage).
87
+ 10. **Deliver**: `export_image` (PNG, or JPEG / WebP in a browser), `export_psd` for Photoshop, `save_paint_document` to keep the painting with its strokes (when the host has storage).
110
88
 
111
89
  ## Best practices
112
90
 
@@ -283,6 +261,8 @@ Contributing while the user paints: suggest, don't paint. Read [references/paint
283
261
  | `move_layer` | Reorder: `index` among siblings (0 = bottom), optionally into `parentId` (or `null` for the top level). |
284
262
  | `merge_layer_down` | Merge a pixel layer into the pixel layer directly below (which keeps its settings). |
285
263
  | `fill_layer` | Fill a pixel layer with `color` at `opacity`: flat, or with `grain` 0..1 following the paper grain (`pressure` 0..1 decides how far into the valleys, default 0.5). The fastest way to lay a ground or a textured tone. Returns the bounds. |
264
+ | `fill_region` | Flood-fill one or more enclosed regions on a pixel layer (`x`, `y` or `points: [{x, y}]`). Set `reference` to an ink layer id (or `"all"` / `"composite"`, or `"layer"`), `closeGap` (0..32 px) to bridge small gaps in line art without leaking, `expand` (-16..16 px, e.g. 1..2 px) to bleed under anti-aliased lines so no halo shows, `grain` (0..1) for paper texture, or `wet: true` to pour a watercolour wash into the region on the wet layer. One undo step. Returns `layerId`, `bounds`, `pixelCount`, `regions`, and `leaked` (`true` when the fill touched the canvas border). |
265
+ | `find_unfilled_regions` | Find enclosed unfilled regions from a reference line-art layer (`reference: inkLayerId`) or `"all"` / `"composite"`, closing gaps up to `closeGap` px and excluding areas already painted on `layerId`. Changes nothing. Returns `regions` sorted largest first with an interior seed `point` (`{x, y}`) ready for `fill_region`, `centroid`, `bounds`, `pixelCount`, and `touchesEdge`. |
286
266
  | `clear_layer` | Remove every pixel of a layer. Returns the bounds that were cleared. |
287
267
 
288
268
  ### Brushes
@@ -335,6 +315,9 @@ Listing, saving, sharing and previewing brushes are the brush library's tools (`
335
315
  | `convert_to_stroke_layer` | Make an empty pixel layer a stroke layer. Returns the layer. |
336
316
  | `rasterize_stroke_layer` | Turn a stroke layer into a plain pixel layer with the same pixels (strokes no longer editable). Do it before erasing, smudging or filling on it. |
337
317
  | `replay_strokes` | Paint recorded `strokeIds` again: exactly, or varied by `dx` / `dy` (px), `rotate` (degrees clockwise), `scale` (brush size follows), `flipX`, `origin`, `pressureScale`, `color`, `brushId`, `layerId`, `repeat` (each copy applies the variation again). One undo step. Returns the new stroke ids, bounds and layers. |
318
+ | `breed_strokes` | Breed `count` (2..12, default 4) mutated variants from recorded `strokeIds` (1..16) as ghost paint proposals: `mutation` (`geometry`, `color`, `brush`, `seed`, each 0..1), `seed`. Returns `proposalIds` and each variant's `diff` and `bounds`. Read [references/evolution.md](references/evolution.md). |
319
+ | `breed_proposal` | Breed `count` (2..12, default 4) next-generation variants from `proposalIds` (1 id mutates it; 2 ids cross their points and brush facets over, then mutate), with `mutation` and `seed`. Returns `proposalIds` and `proposals`. |
320
+ | `get_proposal_genome` | Read a pending proposal's stroke genome (`proposalId`): `strokes` with full brush facets, points, colour and seed. |
338
321
  | `undo_paint` | Undo the last step (a wet stroke's undo puts the wet paint back as it was before it). Returns what was undone and what is next. |
339
322
  | `redo_paint` | Redo the step just undone. |
340
323
 
@@ -442,20 +425,13 @@ The host may add the shared document tools (see `pixerate-agent-tools`). A paint
442
425
  ## Pitfalls
443
426
 
444
427
  - With agent playback on, strokes, fills and replays are painted live by the director, and other writes open their panel (Colour, Wet, Paper, Layers, Effects) and point at the control. Results are unchanged.
445
- - **Stroke-by-stroke drawing is slow and expensive.** Do not draw a detailed picture point by
446
- point. Block in with fills and big strokes, then replay and vary a few good strokes.
447
- - **A hidden or locked layer refuses paint**: show it (`update_layer visible true`) or unlock it.
448
- `transparency` lock is not an error: paint only lands where the layer already has paint.
449
- - **Depth 0 means no grain** whatever the brush; grainy media then look smooth. Smooth bristol
450
- has depth 0.
451
- - **Grain is fixed to the document**, not to the layer: moving content does not move the grain,
452
- and two strokes on the same spot catch the same peaks.
453
- - **Blending tools need paint to blend.** Blender and smudge only move what is on the target
454
- layer: blend on the layer you painted, not on an empty one above it.
455
- - **A dirty brush stays dirty** across strokes and colour changes until `clean_mixer_brush`.
456
- Pick-up lifts only paint on the target layer: the paper and other layers lift nothing.
457
- - **Replays use the recorded load**: a replayed pick-up stroke starts with what the brush carried
458
- when it was painted, not with the current load.
428
+ - **Stroke-by-stroke drawing is slow and expensive.** Do not draw a detailed picture point by point. Block in with fills and big strokes, then replay and vary a few good strokes.
429
+ - **A hidden or locked layer refuses paint**: show it (`update_layer visible true`) or unlock it. `transparency` lock is not an error: paint only lands where the layer already has paint.
430
+ - **Depth 0 means no grain** whatever the brush; grainy media then look smooth. Smooth bristol has depth 0.
431
+ - **Grain is fixed to the document**, not to the layer: moving content does not move the grain, and two strokes on the same spot catch the same peaks.
432
+ - **Blending tools need paint to blend.** Blender and smudge only move what is on the target layer: blend on the layer you painted, not on an empty one above it.
433
+ - **A dirty brush stays dirty** across strokes and colour changes until `clean_mixer_brush`. Pick-up lifts only paint on the target layer: the paper and other layers lift nothing.
434
+ - **Replays use the recorded load**: a replayed pick-up stroke starts with what the brush carried when it was painted, not with the current load.
459
435
  - **Big soft brushes at full flow look flat.** Lower `flow` (airbrush 0.05..0.15) and build up.
460
436
  - **JPEG and WebP need a browser**; in Node use PNG. Exports never upscale (`scale` ≤ 1).
461
437
  - **Symmetry stays on until you turn it off.** Set `mode: "off"` after the symmetric part, or
@@ -0,0 +1,27 @@
1
+ # Evolutionary strokes: breeding and mutating variants
2
+
3
+ Every dry stroke painted in the editor is recorded as a `RecordedStroke` genome: its raw points (with pressure, timing and tilt), its brush facets (`tip`, `dynamics`, `behaviour`, `marks`, `motion`, `colour`), its paint colour and its deterministic `seed`.
4
+
5
+ Rather than guessing facet knobs by hand, you can **breed** a batch of variants from one or more painted strokes, compare their ghost previews and diff summaries, cross two favourites over, or accept one onto a new layer in a single undo step.
6
+
7
+ ## Workflow
8
+
9
+ 1. **Pick parent strokes.** Call `list_strokes` (or use the `strokeId` returned by `paint_stroke` / `stroke_path`). Only dry strokes that `liveStrokeRefusal` permits can be bred — wet, impasto, sticker, eraser, blender, smudge, light and pick-up brushes are refused with the reason.
10
+ 2. **Breed a generation.** Call `breed_strokes` with `strokeIds` (`1..16`), `count` (`2..12`, default `4`), optional `mutation` rates (`geometry`, `color`, `brush`, `seed`, each `0..1`) and an optional deterministic `seed`.
11
+ - Each variant is added as a pending paint proposal (`kind: "strokes"`) rendered through `previewPaint` one after another.
12
+ - The result lists `proposalIds` and `proposals`, each with `proposalId`, `title`, `seed`, `bounds`, a human-readable `diff` summary (`"geometry ±4.2px, scale 0.96×; colour ΔL -0.03, Δh +8°; brush tip.size=18.4, tip.hardness=0.62; seed → 1849201"`) and `changes` tags.
13
+ 3. **Evolve further or cross over.** Call `breed_proposal` with `proposalIds`:
14
+ - **1 proposal id**: mutates that proposal's genome into `count` offspring.
15
+ - **2 proposal ids**: crosses the two parent genomes over — resampling corresponding stroke point paths and mixing their OKLCH colours and numeric brush facets — then mutates each child.
16
+ 4. **Inspect or accept.**
17
+ - Call `get_proposal_genome` with `proposalId` to read the full stroke records (`brush`, `color`, `points`, `seed`) if you want to save the mutated brush with `create_brush`.
18
+ - Call `accept_paint_proposal` to paint the chosen variant onto a new layer as a single undo step, or `reject_paint_proposal` to dismiss variants you don't want.
19
+
20
+ ## Mutation channels (`mutation`)
21
+
22
+ | Channel | Default | What it mutates |
23
+ | --- | --- | --- |
24
+ | `geometry` | `0.35` | Seeded `varyStroke` transform (small offset, rotation, scale and pressure scaling) plus smoothed 3-tap point jitter and pressure drift. Set to `0` to keep the exact path. |
25
+ | `color` | `0.25` | Perceptual drift in OKLCH (`L` ±0.18, `C` ±0.08, `h` ±45° at rate `1.0`), clamped to gamut. Set to `0` to keep the exact colour. |
26
+ | `brush` | `0.3` | Drifts numeric brush facets present on the stroke within their schema bounds (`tip.size`, `tip.hardness`, `tip.spacing`, `tip.roundness`, `tip.angle`, `tip.opacity`, `tip.flow`, `dynamics.sizeJitter`, `dynamics.opacityJitter`, `dynamics.scatter`, `dynamics.angleJitter`, `behaviour.grain`, plus active `marks` particle/bristle/chalk fields). Set to `0` to keep the brush unchanged. |
27
+ | `seed` | `0.5` | Probability of rerolling each stroke's deterministic RNG `seed` so grain, scatter and bristle/particle marks vary even when `geometry`, `color` and `brush` are `0`. |
@@ -46,9 +46,15 @@ This skill is the method. `pixerate-paint-editor` has the full tool reference.
46
46
  4. **Hide the sketch.** `update_layer` the Sketch layer `visible: false` (or lower its `opacity`
47
47
  while inking, then hide it).
48
48
  **Check:** `list_layers` shows it hidden.
49
- 5. **Flats.** `add_layer` "Flats", then `move_layer` it below the Ink layer; fill each shape with
50
- its base colour (`marker` or a flat brush, or `fill_layer` for a background).
51
- **Check:** `pick_color` inside a shape is the flat colour; on a line still the ink.
49
+ 5. **Flats.** `add_layer` "Flats", then `move_layer` it below the Ink layer. Call
50
+ `find_unfilled_regions` (`reference` set to the Ink layer id or `"all"`, `layerId` set to the
51
+ Flats layer, `closeGap: 4..8`) to get each enclosed shape's interior seed `point` and `bounds`.
52
+ Fill each shape in one call with `fill_region` (`x`, `y` or `points` for same-coloured shapes,
53
+ `reference` set to the Ink layer id or `"all"`, `closeGap: 4..8` to bridge small line gaps,
54
+ `expand: 1..2` to bleed under anti-aliased ink edges so no white halo shows, or `wet: true` for a
55
+ watercolour wash). Check `leaked`: if `true`, undo (`undo_paint`) and raise `closeGap` or close
56
+ the open line. Use `fill_layer` for a full-canvas ground.
57
+ **Check:** `pick_color` inside a shape is the flat colour; on a line still the ink; `leaked` is `false`.
52
58
  6. **Shading and light.** `add_layer` "Shading" directly above the flats, `update_layer`
53
59
  `blend: "multiply"` (or `shadow`) and `clipped: true`; paint shadows on the side away from the
54
60
  light. A "Light" layer the same way with `highlight` or `screen`.
@@ -64,7 +70,8 @@ This skill is the method. `pixerate-paint-editor` has the full tool reference.
64
70
  | Sketch | `pencil-hb`, light colour, own layer, hidden at the end |
65
71
  | Line art | `ink-pen` (even), `brush-pen` (swelling); own layer on top |
66
72
  | Clean geometric lines (curves, circles, borders) | `stroke_path` with SVG path data and a `pressure` taper, on the Ink layer |
67
- | Flats | `marker` or a flat brush on a layer under the ink |
73
+ | Flats inside line art | `find_unfilled_regions` then `fill_region` (`reference` = Ink layer id or `"all"`, `closeGap: 4..8`, `expand: 1..2`) on a Flats layer under the ink |
74
+ | Watercolour wash inside line art | `fill_region` with `wet: true`, `reference` = Ink layer id, `closeGap: 4..8`, `expand: 1` |
68
75
  | Patterned or textured flats (sky, gradient, galaxy) | `set_effect_paint` with a provider generator, then a flat dry brush on the Flats layer; `set_color` after |
69
76
  | Textured passes (dry brush, sponge, foliage) | A brush with `tip.grain` (`set_brush` `{ tip: { grain: { source: "sanded", depth: 0.6 } } }`) or an image tip from the brush library, with `dynamics.angleJitter` and `flip` so repeats don't show |
70
77
  | Shadows | Clipped layer, `multiply` or `shadow`, a cool colour |
@@ -75,7 +82,10 @@ This skill is the method. `pixerate-paint-editor` has the full tool reference.
75
82
  ## Recipes
76
83
 
77
84
  **Flats under ink.** `add_layer` "Flats" → `move_layer` with the new layer's id and `index` below
78
- the Ink layer → `set_brush` `marker` → `set_color` → strokes inside the shape.
85
+ the Ink layer → `find_unfilled_regions` `{ reference: inkLayerId, layerId: flatsLayerId, closeGap: 4 }`
86
+ → `fill_region` `{ x, y, color, reference: inkLayerId, closeGap: 4, expand: 1 }` (or pass `points`
87
+ to fill multiple regions of the same colour in one undo step). If `leaked: true`, `undo_paint` and
88
+ increase `closeGap`.
79
89
 
80
90
  **Effect flats.** With an effects provider: `search_effects` (`use` generator) → `describe_effect`
81
91
  → `set_effect_paint` → `marker` strokes inside the shape on the Flats layer (the effect shows
@@ -100,6 +110,7 @@ clipped: true }` → `set_brush` `airbrush` → paint the shadow side.
100
110
 
101
111
  - `get_canvas_info`, `list_layers`, `list_strokes`, `pick_color`, `render_preview`: read and check
102
112
  - `set_paper`, `fill_layer`: the ground and backgrounds
113
+ - `find_unfilled_regions`, `fill_region`: inspect enclosed line-art shapes and fill flats under the ink with gap closing and edge expansion
103
114
  - `add_layer`, `update_layer`, `move_layer`, `remove_layer`: one layer per pass; hide, clip, blend
104
115
  - `set_brush`, `set_color`, `paint_stroke`, `replay_strokes`: sketch, ink, flats and shading
105
116
  - `stroke_path`: clean geometric line art from SVG path data
@@ -20,8 +20,7 @@
20
20
  "solution": [
21
21
  { "tool": "add_layer", "args": { "name": "Flats" } },
22
22
  { "tool": "move_layer", "args": { "layerId": { "$read": "list_layers", "path": "layers.0.id" }, "index": 0 } },
23
- { "tool": "set_brush", "args": { "id": "marker" } },
24
- { "tool": "set_color", "args": { "color": "#f2c14e" } },
25
- { "tool": "paint_stroke", "args": { "points": [{ "x": 14, "y": 16 }, { "x": 50, "y": 16 }, { "x": 50, "y": 24 }, { "x": 14, "y": 24 }, { "x": 14, "y": 32 }, { "x": 50, "y": 32 }, { "x": 50, "y": 40 }, { "x": 14, "y": 40 }, { "x": 14, "y": 48 }, { "x": 50, "y": 48 }] } }
23
+ { "tool": "find_unfilled_regions", "args": { "reference": "all", "closeGap": 4 } },
24
+ { "tool": "fill_region", "args": { "x": 32, "y": 32, "color": "#f2c14e", "reference": "all", "closeGap": 4, "expand": 1 } }
26
25
  ]
27
26
  }