Brush Tool

Draw vectors by hand. Pressure, tilt, smoothing — all built in.

Freehand drawing that outputs clean vector shapes. The brush sweeps a nib shape along your stroke path, producing a filled polygon outline backed by a full vector network. Pressure, tilt, calligraphic angle -- all captured. Change any parameter after drawing and the stroke regenerates from the original hand movement.

This is how Flash's brush worked -- but parametric.


Parametric Strokes

Traditional brush tools bake their output. Draw a stroke, and the raw input is gone. Formo stores the source of truth: raw points with pressure and tilt at stride 4 in a Float32Array, plus the brush configuration that produced the outline.

Source of truth Derived (cached)
-------------- ----------------
rawPoints + brushConfig -> VN outline (nib sweep + curve fit)

Change brush size from 20 to 40 after drawing. Change the nib from oval to rectangle. Crank smoothing from 10 to 80. The stroke regenerates from raw data every time. The original hand movement is never lost.


Nib Shape Sweep

The brush outline is the Minkowski sum envelope of the centerline path and the nib shape. At each sample point, the nib's support function computes the farthest boundary point in the path-normal direction -- O(1) per sample, no iteration.

ParameterRangeEffect
ShapeOval / RectangleNib geometry
Size1--200 pxMaximum nib diameter
Min Size1--100% of SizePressure floor
Angle0--360 degNib rotation
Flatness0--100%Compression (100% = circle, 0% = line)
Smoothing0--100Curve simplification passes

6 parameters. Infinite calligraphic variation.

An angled elliptical nib produces thick strokes in one direction and thin strokes perpendicular -- exactly like a real calligraphy pen. Artists get this effect by drawing naturally, without touching a single bezier handle.

title: "Calligraphic brush stroke"
description: "An angled elliptical nib sweeps along the path -- thick and thin variation emerges from nib geometry"
nodes:
  - type: BRUSH, name: "Stroke", x: 200, y: 200, w: 350, h: 180, fill: "#2C3E50"
config:
  brushConfig: { nibShape: "oval", size: 24, minSize: 0.3, angle: 45, flatness: 0.35, smoothing: 50 }
tools_visible: [select, brush]
ui_visible: [properties]

Pressure and Tilt

With a stylus, the nib scales between minSize and full size based on pen pressure. Light touch gives a thin line. Press hard for full width. The nib shape and angle stay constant -- only scale changes, preserving the calligraphic character.

Tilt sensitivity rotates the virtual nib as you tilt your hand. The same stroke drawn at different angles produces different weight distributions.

Raw input is stored at stride 4: x, y, pressure, tilt. 500 points = 8 KB. Compact enough that every stroke retains its full input history.


Schneider Curve Fitting

Raw sample points become smooth bezier curves through Schneider's algorithm:

  1. Parameterize points by chord length
  2. Fit a single bezier to the entire sequence
  3. If max error exceeds tolerance, split at the worst point and recurse
  4. Store fitted curves as vector network segments with tangents

Tolerance is inversely proportional to the smoothing parameter. Low smoothing = tight fit with more segments. High smoothing = loose fit with fewer segments. The result is a proper vector network -- editable with all vertex tools immediately after drawing.


BrushCanvas and Paint Modes

A BrushCanvas is a container node holding multiple strokes with paint mode interactions. 5 paint modes control how new strokes composite with existing content:

ModeBehavior
Paint NormalNew stroke renders on top
Paint BehindOnly fills blank areas
Paint FillsAffects fills, preserves strokes
Paint SelectionOnly affects selected regions
Paint InsideClips new stroke to the clicked fill boundary

Double-click a BrushCanvas to enter it and add strokes. Escape to exit. Each stroke within the canvas can have its own brush config and color -- select a stroke, change its nib shape, watch it regenerate.

title: "Layered brush canvas"
description: "Multiple brush strokes composited with paint modes -- add and subtract on the same canvas"
nodes:
  - type: BRUSH_CANVAS, name: "Canvas", x: 200, y: 200, w: 300, h: 250
strokes:
  - config: { nibShape: "oval", size: 40, flatness: 0.8 }, color: "#3498DB", paintMode: "normal"
  - config: { nibShape: "oval", size: 20, flatness: 1.0 }, color: "#E74C3C", paintMode: "normal"
  - config: { nibShape: "rect", size: 30, flatness: 0.5 }, paintMode: "erase"
tools_visible: [select, brush, eraser]
ui_visible: [properties]

Eraser as Subtract

The eraser is a brush stroke with paintMode: 'erase'. It stores raw points and nib config like any other stroke. Undo removes it. Change its size after erasing and the subtraction updates. Non-destructive all the way down.


Two Node Types

Standalone BRUSHBRUSH_CANVAS
Use caseQuick one-off strokesMulti-stroke compositions
Paint modesNoYes -- 5 modes
Node treeIndividual node, reorderableContainer with stroke array
CreateAlt+drag in brush modeDefault brush drawing

Both store raw points. Both regenerate from config changes. Convert either to a plain VECTOR node to edit the outline directly in VectorEditMode -- a one-way expansion, like Illustrator's "Expand Appearance."

Deep dive: Vector networks -- the graph topology behind every brush outline
Parametric shapes -- the same regeneration model powers stars, ellipses, and polygons

Flash, Modernized

Flash's brush tool output filled polygons from freehand strokes. It was the fastest way to draw vector art -- artists produced clean shapes without understanding bezier curves.

Flash discarded the raw input. We keep it. Flash offered 9 preset nib shapes. We expose 6 continuous parameters. Flash's output was opaque filled shapes. Ours is a full vector network.

FlashFormo
OutputFilled polygonsVector network
Raw data retainedNoYes -- stride 4 Float32Array
Nib shapes9 presets6 continuous parameters
Post-draw editingNoneFull parametric regeneration
Pressure supportBasicPressure + tilt + min size floor
Paint modes5 modes5 modes (same model)
EraserSeparate toolBrush in subtract mode

Same artistic workflow. Better data model.


Join the Beta

Freehand vector drawing with parametric strokes, pressure sensitivity, and non-destructive editing. The brush tool Flash should have had.

Request Beta Access -->

← НазадParametric Shapes