Skip to content
Painter

The painter seam

The primitives every widget is drawn with, the optional capabilities a painter may add, and the pixel and cell painters.

go-widgets/painter defines the one interface every widget draws through:

type Painter interface {
	FillRect(r Rect, c RGBA)
	StrokeRect(r Rect, c RGBA, lineW int)
	FillRoundRect(r Rect, radius int, c RGBA)
	StrokeRoundRect(r Rect, radius int, c RGBA, lineW int)
	PutPixel(x, y int, c RGBA)
	Text(x, y int, s string, ink RGBA)
	Size() (w, h int)
}

The set is small on purpose: every back-end must implement all of it, and a terminal grid cannot round a corner or vary a stroke width. So the contract says what happens when it cannot — StrokeRect’s width is a hint a cell grid ignores, and FillRoundRect falls back to a square fill there.

Optional capabilities

What not every surface can do is not in the base interface. A widget that needs it type-asserts, and draws something sensible when the answer is no:

InterfaceMethodsUsed for
ClipperPushClip, PopClipkeeping a scrolled child inside its parent’s bounds
TranslatorPushTranslate, PopTranslatedrawing a child in its own coordinates
PathPainterFillPath, StrokePathcurves, charts, anti-aliased shapes
ImagePainterDrawImageicons, thumbnails, pictures
MaskPainterDrawMaskglyphs and other coverage masks in one colour
FacePainterTextFacetext in a specific font face and size
if c, ok := p.(painter.Clipper); ok {
	c.PushClip(bounds)
	defer c.PopClip()
}

The two painters

Writes intoPresented by
NewPixelPainter(buf, w, h)a caller-owned RGBA []byte (NewPixelPainterBGRA for BGRA surfaces)a native window, a browser canvas, an Android surface, a PNG or SVG
NewCellPainter(w, h)a grid of cells (rune, foreground, background) with a 24-bit ANSI serialisera terminal, through tui

The buffer stays the caller’s. A PixelPainter only translates primitives into writes, so the same []byte can be handed to a window back-end, a <canvas> or an image encoder without a copy in between.

Trying it

The repository’s own demos draw the same three widgets through both painters:

go run ./cmd/wui-demo --out demo.png     # pixels, written as a PNG
go run ./cmd/tui-demo --theme dark       # cells, written as ANSI to stdout

and go-widgets.github.io/painter shows the pixel painter in a browser.

Created on by tannevaled

Modified on by tannevaled