stroke

package
v0.33.1 Latest Latest
Warning

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

Go to latest
Published: Mar 5, 2026 License: MIT Imports: 1 Imported by: 0

Documentation

Overview

Package stroke provides stroke expansion algorithms for converting stroked paths to filled outlines.

This package implements CPU-side stroke expansion following tiny-skia and kurbo patterns. The algorithm converts a path with stroke style into a filled path suitable for GPU rasterization.

Algorithm Overview

Stroke expansion works by building two parallel offset paths:

  • Forward path: Offset by +width/2 perpendicular to the tangent
  • Backward path: Offset by -width/2 perpendicular to the tangent

The final filled path is constructed by:

  1. Forward path goes forward
  2. End cap connects forward to backward
  3. Backward path is reversed
  4. Start cap connects backward to forward and closes

Line Caps

Line caps define the shape of stroke endpoints:

  • LineCapButt: Flat cap ending exactly at the endpoint
  • LineCapRound: Semicircular cap with radius = width/2
  • LineCapSquare: Square cap extending width/2 beyond the endpoint

Line Joins

Line joins define how stroke segments connect:

  • LineJoinMiter: Sharp corner (limited by miter limit)
  • LineJoinRound: Circular arc at corners
  • LineJoinBevel: Straight line across the corner

Usage

style := stroke.Stroke{
    Width:      2.0,
    Cap:        stroke.LineCapRound,
    Join:       stroke.LineJoinMiter,
    MiterLimit: 4.0,
}

expander := stroke.NewStrokeExpander(style)
expander.SetTolerance(0.1) // Optional: adjust curve flattening

inputPath := []stroke.PathElement{
    stroke.MoveTo{Point: stroke.Point{X: 0, Y: 0}},
    stroke.LineTo{Point: stroke.Point{X: 100, Y: 0}},
    stroke.LineTo{Point: stroke.Point{X: 100, Y: 100}},
}

filledPath := expander.Expand(inputPath)

Performance

The expander is optimized for typical use cases:

  • Simple lines: ~2 microseconds
  • Complex paths (100 segments): ~50-60 microseconds
  • Cubic curves are flattened to line segments based on tolerance

References

The algorithm is based on:

  • tiny-skia (Rust): path/src/stroker.rs
  • kurbo (Rust): src/stroke.rs

See GPU-STK-001 in docs/dev/kanban/ for the full task specification.

Package stroke provides stroke expansion algorithms for converting stroked paths to filled outlines.

This package implements CPU-side stroke expansion following tiny-skia and kurbo patterns. The algorithm converts a path with stroke style into a filled path suitable for GPU rasterization.

Key algorithm insight: A stroke is converted to a FILL path where:

  • The outer offset path goes forward
  • The inner offset path is reversed
  • Line caps connect the endpoints
  • Line joins connect the segments

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Close

type Close struct{}

Close closes the path.

type CubicTo

type CubicTo struct{ Control1, Control2, Point Point }

CubicTo draws a cubic Bezier curve.

type LineCap

type LineCap int

LineCap specifies the shape of line endpoints.

const (
	// LineCapButt specifies a flat line cap.
	LineCapButt LineCap = iota
	// LineCapRound specifies a rounded line cap.
	LineCapRound
	// LineCapSquare specifies a square line cap.
	LineCapSquare
)

type LineJoin

type LineJoin int

LineJoin specifies the shape of line joins.

const (
	// LineJoinMiter specifies a sharp (mitered) join.
	LineJoinMiter LineJoin = iota
	// LineJoinRound specifies a rounded join.
	LineJoinRound
	// LineJoinBevel specifies a beveled join.
	LineJoinBevel
)

type LineTo

type LineTo struct{ Point Point }

LineTo draws a line.

type MoveTo

type MoveTo struct{ Point Point }

MoveTo moves to a point.

type PathElement

type PathElement interface {
	// contains filtered or unexported methods
}

PathElement represents an element in a path.

type Point

type Point struct {
	X, Y float64
}

Point represents a 2D point (internal copy to avoid import cycle).

func (Point) Add

func (p Point) Add(v Vec2) Point

Add returns the sum of two points.

func (Point) Distance

func (p Point) Distance(q Point) float64

Distance returns the distance between two points.

func (Point) Lerp

func (p Point) Lerp(q Point, t float64) Point

Lerp performs linear interpolation between two points.

func (Point) Sub

func (p Point) Sub(q Point) Vec2

Sub returns the difference between two points as a vector.

func (Point) Vec2

func (p Point) Vec2() Vec2

Vec2 returns the point as a vector from the origin.

type QuadTo

type QuadTo struct{ Control, Point Point }

QuadTo draws a quadratic Bezier curve.

type Stroke

type Stroke struct {
	Width      float64
	Cap        LineCap
	Join       LineJoin
	MiterLimit float64
}

Stroke defines the style for stroke expansion.

func DefaultStroke

func DefaultStroke() Stroke

DefaultStroke returns a stroke with default settings.

type StrokeExpander

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

StrokeExpander converts stroked paths to filled paths. This follows the kurbo stroke expansion algorithm.

func NewStrokeExpander

func NewStrokeExpander(style Stroke) *StrokeExpander

NewStrokeExpander creates a new stroke expander with the given style.

func (*StrokeExpander) Expand

func (e *StrokeExpander) Expand(elements []PathElement) []PathElement

Expand converts a stroked path to a fill path.

func (*StrokeExpander) SetTolerance

func (e *StrokeExpander) SetTolerance(tolerance float64)

SetTolerance sets the curve flattening tolerance.

type Vec2

type Vec2 struct {
	X, Y float64
}

Vec2 represents a 2D vector.

func (Vec2) Add

func (v Vec2) Add(w Vec2) Vec2

Add returns the sum of two vectors.

func (Vec2) Angle

func (v Vec2) Angle() float64

Angle returns the angle of the vector in radians.

func (Vec2) Cross

func (v Vec2) Cross(w Vec2) float64

Cross returns the 2D cross product (z-component of 3D cross).

func (Vec2) Dot

func (v Vec2) Dot(w Vec2) float64

Dot returns the dot product of two vectors.

func (Vec2) Length

func (v Vec2) Length() float64

Length returns the length of the vector.

func (Vec2) LengthSquared

func (v Vec2) LengthSquared() float64

LengthSquared returns the squared length of the vector.

func (Vec2) Neg

func (v Vec2) Neg() Vec2

Neg returns the negated vector.

func (Vec2) Normalize

func (v Vec2) Normalize() Vec2

Normalize returns a unit vector in the same direction.

func (Vec2) Perp

func (v Vec2) Perp() Vec2

Perp returns the perpendicular vector (rotated 90 degrees counter-clockwise).

func (Vec2) Scale

func (v Vec2) Scale(s float64) Vec2

Scale returns the vector scaled by s.

func (Vec2) Sub

func (v Vec2) Sub(w Vec2) Vec2

Sub returns the difference of two vectors.

func (Vec2) ToPoint

func (v Vec2) ToPoint() Point

ToPoint converts the vector to a point.

Jump to

Keyboard shortcuts

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