Paint Engine
First Painted Stroke
The paint engine renders brushstrokes as dab sequences onto a raster surface — brushes are data, strokes are data. The simplest form is a :paint/surface node listing strokes; each is a brush, a color, a radius, and a series of [x y] points the dab follows:
{:node/type :paint/surface
:paint/size [600 400]
:paint/strokes
[{:paint/brush :chalk
:paint/color [:color/rgb 80 60 40]
:paint/radius 12.0
:paint/points [[50 100] [300 60] [550 100]]}]}
The dab is laid down along the points in order.
Brush Presets
Six presets cover the common media — name one as :paint/brush, or override the brush directly:
;; Use a preset
:paint/brush :chalk ;; :pencil :ink :marker :watercolor :oil :chalk
;; Or override the brush — tip shape, hardness, flow, blend
:paint/brush {:brush/tip {:tip/shape :ellipse :tip/hardness 0.9}
:brush/paint {:paint/flow 0.7 :paint/blend :multiply}}Tip shapes: :round, :ellipse, :chisel, :rect, :line. Blend modes: :normal, :multiply, :screen, :overlay, :darken, :lighten, :add.
Painting Paths
To paint along curves, wrap brush-painted :shape/path nodes in a group carrying :paint/surface. Each path's commands become a stroke, and all of them render onto the same surface — so later strokes lay over earlier ones:
{:node/type :group
:paint/surface {:paint/size [800 400]}
:group/children
[{:node/type :shape/path
:path/commands [[:move-to [20 250]]
[:curve-to [200 100] [400 350] [780 200]]]
:paint/brush :watercolor
:paint/color [:color/hsl 210 0.45 0.65]
:paint/radius 45.0}
;; Ink detail on top
{:node/type :shape/path
:path/commands [[:move-to [120 220]]
[:curve-to [300 150] [500 280] [680 180]]]
:paint/brush :ink
:paint/color [:color/rgb 25 30 50]
:paint/radius 2.5}]}
Give each painted path a :paint/brush, :paint/color, and :paint/radius — and no :style/fill or :style/stroke.