canvas

package
v0.0.12 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 4, 2026 License: MIT Imports: 13 Imported by: 0

Documentation

Overview

Package canvas defines the rendering backend abstraction. All drawing operations go through the Canvas interface, which decouples geometry rendering from the specific graphics library (gogpu/gg, SVG, etc.).

Index

Constants

View Source
const (
	ShapeCircle       = "circle"
	ShapeSquare       = "square"
	ShapeTriangle     = "triangle"
	ShapeTriangleDown = "triangleDown"
	ShapeDiamond      = "diamond"
	ShapePlus         = "plus"
	ShapeCross        = "cross"
	ShapeStar         = "star"
	ShapePentagon     = "pentagon"
	ShapeHexagon      = "hexagon"
)

Shape name constants — single source of truth for all shape identifiers used throughout the library (scales, drawers, legends, canvas backends).

Variables

View Source
var (
	AnchorTopLeft      = TextAnchor{0, 0}
	AnchorTopCenter    = TextAnchor{0.5, 0}
	AnchorTopRight     = TextAnchor{1, 0}
	AnchorMiddleLeft   = TextAnchor{0, 0.5}
	AnchorCenter       = TextAnchor{0.5, 0.5}
	AnchorMiddleRight  = TextAnchor{1, 0.5}
	AnchorBottomLeft   = TextAnchor{0, 1}
	AnchorBottomCenter = TextAnchor{0.5, 1}
	AnchorBottomRight  = TextAnchor{1, 1}
)

Common text anchors.

Functions

func DrawShapePath added in v0.0.8

func DrawShapePath(c Canvas, shape string, cx, cy, r float64)

DrawShapePath constructs a shape path using the Canvas path API. This is the fallback implementation used by RecordingCanvas and other backends that do not have native polygon primitives. RasterCanvas uses gg.Context.DrawRegularPolygon directly instead — see RasterCanvas.DrawShape.

func ExportPDF

func ExportPDF(r *recording.Recording, w io.Writer) (int64, error)

ExportPDF replays a recording into the native PDF backend and writes to w.

func ExportSVG

func ExportSVG(r *recording.Recording, w io.Writer) (int64, error)

ExportSVG replays a recording into the native SVG backend and writes to w.

func ExportSVGWithMeta added in v0.0.11

func ExportSVGWithMeta(r *recording.Recording, meta map[int]map[string]string, w io.Writer) (int64, error)

ExportSVGWithMeta replays a recording into the SVG backend with per-primitive metadata (tooltips, links, ARIA labels). The metadata map is keyed by draw-op sequence number, matching RecordingCanvas.MetadataMap.

func IsStrokeShape added in v0.0.8

func IsStrokeShape(shape string) bool

IsStrokeShape reports whether the shape should be rendered with stroke rather than fill (i.e., line-based shapes).

func Shapes added in v0.0.8

func Shapes() []string

Shapes returns the ordered list of all supported shape names. The order matches the default cycle used by [scale.ShapeScale].

Types

type Canvas

type Canvas interface {

	// Save pushes the current graphics state (color, transform, clip) onto a stack.
	Save()
	// Restore pops the graphics state stack.
	Restore()

	// Translate shifts the origin by (dx, dy).
	Translate(dx, dy float64)
	// Rotate applies a rotation of angle radians around the current origin.
	Rotate(angle float64)
	// ScaleXY applies a non-uniform scale.
	ScaleXY(sx, sy float64)

	// MoveTo starts a new sub-path at (x, y).
	MoveTo(x, y float64)
	// LineTo adds a line segment from the current point to (x, y).
	LineTo(x, y float64)
	// QuadraticTo adds a quadratic Bézier curve to (x, y) via control point (cx, cy).
	QuadraticTo(cx, cy, x, y float64)
	// CubicTo adds a cubic Bézier curve to (x, y) via control points (cx1, cy1) and (cx2, cy2).
	CubicTo(cx1, cy1, cx2, cy2, x, y float64)
	// ClosePath closes the current sub-path with a line to the start point.
	ClosePath()
	// ClearPath discards the current path without drawing.
	ClearPath()

	// SetColor sets the current drawing color for both fill and stroke.
	SetColor(c color.Color)
	// SetRGBA sets the current drawing color from normalized components.
	SetRGBA(r, g, b, a float64)
	// SetLineWidth sets the stroke width in pixels.
	SetLineWidth(w float64)
	// SetLineDash sets the dash pattern. Pass nil or empty for solid lines.
	SetLineDash(pattern ...float64)
	// Fill fills the current path with the current color, then clears the path.
	Fill()
	// Stroke draws the current path outline, then clears the path.
	Stroke()
	// FillPreserve fills without clearing the path (allows subsequent stroke).
	FillPreserve()
	// Clip clips rendering to the current path. Call after constructing a path
	// (e.g. DrawRectangle). Use Save/Restore to undo the clip.
	Clip()
	// ClipRect clips rendering to the axis-aligned rectangle (x, y, w, h).
	// This is much faster than DrawRectangle+Clip for rectangular clip regions
	// because the backend can use a GPU scissor rect instead of rasterizing
	// a full-resolution clip mask.
	ClipRect(x, y, w, h float64)

	// DrawCircle adds a circle path centered at (cx, cy) with radius r.
	DrawCircle(cx, cy, r float64)
	// DrawRectangle adds a rectangle path at (x, y) with dimensions (w, h).
	DrawRectangle(x, y, w, h float64)
	// DrawLine adds a line path from (x1, y1) to (x2, y2).
	DrawLine(x1, y1, x2, y2 float64)
	// DrawShape adds a path for the specified shape centered at (cx, cy) with size/radius r.
	// Supported shapes: "circle", "square", "triangle", "diamond", "triangleDown",
	// "plus", "cross", "star", "pentagon", "hexagon".
	DrawShape(shape string, cx, cy, r float64)

	// SetFontSize sets the font size in points.
	SetFontSize(size float64)
	// SetTabularNums enables or disables tabular (monospaced) digit widths
	// for subsequent text rendering. When enabled, digits occupy uniform
	// horizontal space for aligned numeric columns (e.g., axis tick labels).
	// Backends that don't support OpenType features may ignore this.
	SetTabularNums(enabled bool)
	// DrawStringAnchored draws text at (x, y) with anchor (ax, ay) ∈ [0,1].
	// (0,0) = top-left, (0.5,0.5) = center, (1,1) = bottom-right.
	DrawStringAnchored(text string, x, y, ax, ay float64)
	// MeasureString returns the width and height of the rendered text.
	MeasureString(text string) (w, h float64)

	// Clear fills the entire canvas with the given color.
	Clear(c color.Color)
	// Width returns the canvas width in pixels.
	Width() int
	// Height returns the canvas height in pixels.
	Height() int
	// DrawImage composites the given image onto the canvas at position (x, y).
	// Used for compositing panel sub-canvases during parallel rendering.
	DrawImage(img image.Image, x, y float64)

	// SetMetadata attaches per-primitive metadata to the next drawing call.
	// Only backends that support metadata (SVG) emit it; others (PNG, PDF)
	// silently discard it. The metadata is consumed by the next Fill, Stroke,
	// or DrawStringAnchored call, then cleared.
	//
	// Supported keys: "title" (<title> tooltip), "href" (hyperlink),
	// "aria_label" (ARIA accessibility label).
	SetMetadata(meta map[string]string)

	// Close releases backend resources (GPU buffers, etc.).
	// Implementations that hold no resources may return nil.
	Close() error
}

Canvas is the core rendering abstraction. Implementations provide the actual drawing primitives targeting specific backends (CPU rasterizer, GPU pipeline, SVG writer, etc.).

The API is modeled after gogpu/gg's Context for natural integration, but abstracted so alternative backends can be swapped without changing any rendering logic.

type FontWeight

type FontWeight int

FontWeight describes font weight for text rendering.

const (
	WeightNormal FontWeight = 400
	WeightBold   FontWeight = 700
)

FontWeight constants for common weights.

type RasterCanvas added in v0.0.10

type RasterCanvas struct {
	// contains filtered or unexported fields
}

RasterCanvas wraps a gogpu/gg.Context to implement the Canvas interface. This is the primary CPU-based rendering backend.

func NewRasterCanvas added in v0.0.10

func NewRasterCanvas(width, height int) *RasterCanvas

NewRasterCanvas creates a Canvas backed by a gogpu/gg rasterizer.

func NewRasterCanvasCPU added in v0.0.10

func NewRasterCanvasCPU(width, height int) *RasterCanvas

NewRasterCanvasCPU creates a Canvas that uses pure-CPU analytic rasterization, bypassing the GPU accelerator. This produces deterministic output even when multiple canvases are created in a single process (useful for tests).

func RasterFromContext added in v0.0.10

func RasterFromContext(ctx *gg.Context) *RasterCanvas

RasterFromContext wraps an existing gg.Context.

func (*RasterCanvas) Clear added in v0.0.10

func (c *RasterCanvas) Clear(col color.Color)

Clear fills the entire canvas with the given color. Uses DrawRectangle+Fill instead of ctx.Clear() because the GPU accelerator needs a draw command to update the surface — ctx.Clear() only writes to the CPU pixmap and leaves the GPU surface stale.

func (*RasterCanvas) ClearPath added in v0.0.10

func (c *RasterCanvas) ClearPath()

ClearPath discards the current path without drawing.

func (*RasterCanvas) Clip added in v0.0.10

func (c *RasterCanvas) Clip()

Clip clips rendering to the current path.

func (*RasterCanvas) ClipRect added in v0.0.10

func (c *RasterCanvas) ClipRect(x, y, w, h float64)

ClipRect clips rendering to the axis-aligned rectangle (x, y, w, h). Uses gg.Context.ClipRect which pushes a rect onto the clip stack without rasterizing a full-resolution anti-aliased clip mask. Profile showed the generic Clip() path consuming ~75% of frame time via MaskClipper.rasterizeScanlineAA — this bypasses that entirely.

func (*RasterCanvas) Close added in v0.0.10

func (c *RasterCanvas) Close() error

Close releases the underlying gg.Context's GPU resources. Always call Close (or use defer) when the canvas is no longer needed to avoid GPU resource leaks (wgpu BindGroup/Buffer finalizer warnings).

func (*RasterCanvas) ClosePath added in v0.0.10

func (c *RasterCanvas) ClosePath()

ClosePath closes the current sub-path.

func (*RasterCanvas) Context added in v0.0.10

func (c *RasterCanvas) Context() *gg.Context

Context returns the underlying gg.Context for direct access when needed (e.g., font loading, image export).

func (*RasterCanvas) CubicTo added in v0.0.10

func (c *RasterCanvas) CubicTo(cx1, cy1, cx2, cy2, x, y float64)

CubicTo adds a cubic Bézier curve via (cx1, cy1) and (cx2, cy2) to (x, y).

func (*RasterCanvas) DrawCircle added in v0.0.10

func (c *RasterCanvas) DrawCircle(cx, cy, r float64)

DrawCircle adds a circle path centered at (cx, cy) with radius r.

func (*RasterCanvas) DrawImage added in v0.0.10

func (c *RasterCanvas) DrawImage(img image.Image, x, y float64)

DrawImage composites img onto the canvas at pixel position (x, y).

func (*RasterCanvas) DrawLine added in v0.0.10

func (c *RasterCanvas) DrawLine(x1, y1, x2, y2 float64)

DrawLine adds a line path from (x1, y1) to (x2, y2).

func (*RasterCanvas) DrawRectangle added in v0.0.10

func (c *RasterCanvas) DrawRectangle(x, y, w, h float64)

DrawRectangle adds a rectangle path at (x, y) with dimensions (w, h).

func (*RasterCanvas) DrawShape added in v0.0.10

func (c *RasterCanvas) DrawShape(shape string, cx, cy, r float64)

DrawShape adds a path for the specified shape centered at (cx, cy) with size/radius r. Uses gg.Context.DrawRegularPolygon for polygon shapes for optimal rendering.

func (*RasterCanvas) DrawStringAnchored added in v0.0.10

func (c *RasterCanvas) DrawStringAnchored(s string, x, y, ax, ay float64)

DrawStringAnchored draws text at (x, y) with anchor (ax, ay).

func (*RasterCanvas) EncodePNG added in v0.0.10

func (c *RasterCanvas) EncodePNG(w io.Writer) error

EncodePNG writes the canvas as PNG to the given writer.

func (*RasterCanvas) Fill added in v0.0.10

func (c *RasterCanvas) Fill()

Fill fills the current path with the current color, then clears the path.

func (*RasterCanvas) FillPreserve added in v0.0.10

func (c *RasterCanvas) FillPreserve()

FillPreserve fills without clearing the path (allows subsequent stroke).

func (*RasterCanvas) Height added in v0.0.10

func (c *RasterCanvas) Height() int

Height returns the canvas height in pixels.

func (*RasterCanvas) Image added in v0.0.10

func (c *RasterCanvas) Image() image.Image

Image returns the underlying image.

func (*RasterCanvas) LineTo added in v0.0.10

func (c *RasterCanvas) LineTo(x, y float64)

LineTo adds a line segment from the current point to (x, y).

func (*RasterCanvas) MeasureString added in v0.0.10

func (c *RasterCanvas) MeasureString(s string) (float64, float64)

MeasureString returns the width and height of the rendered text.

func (*RasterCanvas) MoveTo added in v0.0.10

func (c *RasterCanvas) MoveTo(x, y float64)

MoveTo starts a new sub-path at (x, y).

func (*RasterCanvas) QuadraticTo added in v0.0.10

func (c *RasterCanvas) QuadraticTo(cx, cy, x, y float64)

QuadraticTo adds a quadratic Bézier curve via control point (cx, cy) to (x, y).

func (*RasterCanvas) Restore added in v0.0.10

func (c *RasterCanvas) Restore()

Restore pops the graphics state from the stack.

func (*RasterCanvas) Rotate added in v0.0.10

func (c *RasterCanvas) Rotate(angle float64)

Rotate applies a rotation of angle radians.

func (*RasterCanvas) Save added in v0.0.10

func (c *RasterCanvas) Save()

Save pushes the current graphics state onto the stack.

func (*RasterCanvas) SavePNG added in v0.0.10

func (c *RasterCanvas) SavePNG(path string) error

SavePNG writes the canvas to a PNG file.

func (*RasterCanvas) ScaleXY added in v0.0.10

func (c *RasterCanvas) ScaleXY(sx, sy float64)

ScaleXY applies a non-uniform scale.

func (*RasterCanvas) SetColor added in v0.0.10

func (c *RasterCanvas) SetColor(col color.Color)

SetColor sets the current drawing color for both fill and stroke.

func (*RasterCanvas) SetFontSize added in v0.0.10

func (c *RasterCanvas) SetFontSize(size float64)

SetFontSize resolves the best available font at the given size. Resolution order: system font via fonts resolver -> embedded Go Regular fallback.

func (*RasterCanvas) SetLineDash added in v0.0.10

func (c *RasterCanvas) SetLineDash(pattern ...float64)

SetLineDash sets the dash pattern. Pass nil or empty for solid lines.

func (*RasterCanvas) SetLineWidth added in v0.0.10

func (c *RasterCanvas) SetLineWidth(w float64)

SetLineWidth sets the stroke width in pixels.

func (*RasterCanvas) SetMetadata added in v0.0.11

func (c *RasterCanvas) SetMetadata(_ map[string]string)

SetMetadata is a no-op for raster output — PNG has no metadata output path.

func (*RasterCanvas) SetRGBA added in v0.0.10

func (c *RasterCanvas) SetRGBA(r, g, b, a float64)

SetRGBA sets the current drawing color from normalized components.

func (*RasterCanvas) SetTabularNums added in v0.0.10

func (c *RasterCanvas) SetTabularNums(enabled bool)

SetTabularNums enables or disables tabular (monospaced) digit widths.

func (*RasterCanvas) Stroke added in v0.0.10

func (c *RasterCanvas) Stroke()

Stroke draws the current path outline, then clears the path.

func (*RasterCanvas) Translate added in v0.0.10

func (c *RasterCanvas) Translate(dx, dy float64)

Translate shifts the origin by (dx, dy).

func (*RasterCanvas) Width added in v0.0.10

func (c *RasterCanvas) Width() int

Width returns the canvas width in pixels.

type RecordingCanvas

type RecordingCanvas struct {
	// contains filtered or unexported fields
}

RecordingCanvas wraps a recording.Recorder to implement the Canvas interface. All drawing operations are captured as a recording that can later be replayed into any backend (SVG, PDF, raster, etc.) via [Recording.Playback].

func NewRecordingCanvas

func NewRecordingCanvas(width, height int) *RecordingCanvas

NewRecordingCanvas creates a Canvas that records all drawing operations. After rendering, call RecordingCanvas.FinishRecording and replay into the desired backend (e.g., SVG, PDF).

func (*RecordingCanvas) Clear

func (c *RecordingCanvas) Clear(col color.Color)

Clear fills the entire canvas with the given color.

The recorder captures this as two draw ops during SVG playback:

  1. rec.Clear() → FillRect (transparent background clear)
  2. rec.DrawRectangle + rec.Fill → FillPath (opaque fill)

We must increment drawOpCount for each to keep it in sync with the SVG backend's emitDrawOp counter.

func (*RecordingCanvas) ClearPath

func (c *RecordingCanvas) ClearPath()

ClearPath discards the current path without drawing.

func (*RecordingCanvas) Clip

func (c *RecordingCanvas) Clip()

Clip clips rendering to the current path.

func (*RecordingCanvas) ClipRect added in v0.0.10

func (c *RecordingCanvas) ClipRect(x, y, w, h float64)

ClipRect clips rendering to the axis-aligned rectangle (x, y, w, h). Falls back to DrawRectangle+Clip since recording.Recorder does not have a dedicated ClipRect. This is acceptable because RecordingCanvas is used for SVG/PDF export, not interactive rendering.

func (*RecordingCanvas) Close added in v0.0.5

func (c *RecordingCanvas) Close() error

Close is a no-op for RecordingCanvas (no GPU resources to release).

func (*RecordingCanvas) ClosePath

func (c *RecordingCanvas) ClosePath()

ClosePath closes the current sub-path.

func (*RecordingCanvas) CubicTo

func (c *RecordingCanvas) CubicTo(cx1, cy1, cx2, cy2, x, y float64)

CubicTo adds a cubic Bézier curve via (cx1, cy1) and (cx2, cy2) to (x, y).

func (*RecordingCanvas) DrawCircle

func (c *RecordingCanvas) DrawCircle(cx, cy, r float64)

DrawCircle adds a circle path centered at (cx, cy) with radius r.

func (*RecordingCanvas) DrawImage added in v0.0.6

func (c *RecordingCanvas) DrawImage(_ image.Image, _, _ float64)

DrawImage is a no-op for RecordingCanvas. SVG/PDF recording does not support raster compositing; parallel panel rendering is only used by raster backends (RasterCanvas).

func (*RecordingCanvas) DrawLine

func (c *RecordingCanvas) DrawLine(x1, y1, x2, y2 float64)

DrawLine adds a line path from (x1, y1) to (x2, y2).

func (*RecordingCanvas) DrawRectangle

func (c *RecordingCanvas) DrawRectangle(x, y, w, h float64)

DrawRectangle adds a rectangle path at (x, y) with dimensions (w, h).

func (*RecordingCanvas) DrawShape added in v0.0.8

func (c *RecordingCanvas) DrawShape(shape string, cx, cy, r float64)

DrawShape adds a path for the specified shape centered at (cx, cy) with size/radius r.

func (*RecordingCanvas) DrawStringAnchored

func (c *RecordingCanvas) DrawStringAnchored(s string, x, y, ax, ay float64)

DrawStringAnchored draws text at (x, y) with anchor (ax, ay).

The anchor is pre-applied here rather than deferred to the recorder: the recording playback drops the anchor (its Backend.DrawText takes no anchor and is handed a nil face), so anchored text would otherwise render left-aligned at the baseline in SVG/PDF. We replicate gg's exact anchor math against the current face and record a base-positioned DrawString, keeping vector text aligned with the raster output.

func (*RecordingCanvas) Fill

func (c *RecordingCanvas) Fill()

Fill fills the current path with the current color, then clears the path.

func (*RecordingCanvas) FillPreserve

func (c *RecordingCanvas) FillPreserve()

FillPreserve fills without clearing the path (allows subsequent stroke).

func (*RecordingCanvas) FinishRecording

func (c *RecordingCanvas) FinishRecording() *recording.Recording

FinishRecording completes the recording and returns the captured operations.

func (*RecordingCanvas) Height

func (c *RecordingCanvas) Height() int

Height returns the canvas height in pixels.

func (*RecordingCanvas) LineTo

func (c *RecordingCanvas) LineTo(x, y float64)

LineTo adds a line segment from the current point to (x, y).

func (*RecordingCanvas) MeasureString

func (c *RecordingCanvas) MeasureString(s string) (float64, float64)

MeasureString returns the width and height of the rendered text.

func (*RecordingCanvas) MetadataMap added in v0.0.11

func (c *RecordingCanvas) MetadataMap() map[int]map[string]string

MetadataMap returns the metadata side-channel for export. Keyed by draw-op sequence number (Fill, Stroke, DrawText).

func (*RecordingCanvas) MoveTo

func (c *RecordingCanvas) MoveTo(x, y float64)

MoveTo starts a new sub-path at (x, y).

func (*RecordingCanvas) QuadraticTo

func (c *RecordingCanvas) QuadraticTo(cx, cy, x, y float64)

QuadraticTo adds a quadratic Bézier curve via control point (cx, cy) to (x, y).

func (*RecordingCanvas) Restore

func (c *RecordingCanvas) Restore()

Restore pops the graphics state from the stack.

func (*RecordingCanvas) Rotate

func (c *RecordingCanvas) Rotate(angle float64)

Rotate applies a rotation of angle radians.

func (*RecordingCanvas) Save

func (c *RecordingCanvas) Save()

Save pushes the current graphics state onto the stack.

func (*RecordingCanvas) ScaleXY

func (c *RecordingCanvas) ScaleXY(sx, sy float64)

ScaleXY applies a non-uniform scale.

func (*RecordingCanvas) SetColor

func (c *RecordingCanvas) SetColor(col color.Color)

SetColor sets the current drawing color for both fill and stroke.

func (*RecordingCanvas) SetFontSize

func (c *RecordingCanvas) SetFontSize(size float64)

SetFontSize resolves the best available font at the given size.

func (*RecordingCanvas) SetLineDash

func (c *RecordingCanvas) SetLineDash(pattern ...float64)

SetLineDash sets the dash pattern. Pass nil or empty for solid lines.

func (*RecordingCanvas) SetLineWidth

func (c *RecordingCanvas) SetLineWidth(w float64)

SetLineWidth sets the stroke width in pixels.

func (*RecordingCanvas) SetMetadata added in v0.0.11

func (c *RecordingCanvas) SetMetadata(meta map[string]string)

SetMetadata attaches per-primitive metadata to the next draw call. The metadata is stored in a side-channel indexed by draw-op sequence number and emitted during SVG export.

func (*RecordingCanvas) SetRGBA

func (c *RecordingCanvas) SetRGBA(r, g, b, a float64)

SetRGBA sets the current drawing color from normalized components.

func (*RecordingCanvas) SetTabularNums added in v0.0.5

func (c *RecordingCanvas) SetTabularNums(enabled bool)

SetTabularNums enables or disables tabular (monospaced) digit widths.

func (*RecordingCanvas) Stroke

func (c *RecordingCanvas) Stroke()

Stroke draws the current path outline, then clears the path.

func (*RecordingCanvas) Translate

func (c *RecordingCanvas) Translate(dx, dy float64)

Translate shifts the origin by (dx, dy).

func (*RecordingCanvas) Width

func (c *RecordingCanvas) Width() int

Width returns the canvas width in pixels.

type TextAnchor

type TextAnchor struct {
	X, Y float64 // [0,1] where (0,0) = top-left, (1,1) = bottom-right
}

TextAnchor defines text alignment as normalized coordinates.

Directories

Path Synopsis
Package gpu opts in GPU acceleration.
Package gpu opts in GPU acceleration.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL