Skip to main content

Drawing

APIs for vector paths, styling, and rendering commands.


Path

Vector path for custom geometry.

Constructors

Path.new()

Creates an empty path.

Path.new(): Path

Methods

path:moveTo(point)

Moves the pen to a new position, starting a new subpath.

path:moveTo(point: Vector)

path:lineTo(point)

Draws a straight line from the current position.

path:lineTo(point: Vector)

path:quadTo(control, end)

Draws a quadratic Bezier curve.

path:quadTo(control: Vector, endPoint: Vector)

path:cubicTo(c1, c2, end)

Draws a cubic Bezier curve.

path:cubicTo(controlOut: Vector, controlIn: Vector, endPoint: Vector)

path:close()

Closes the current subpath with a line to the start.

path:close()

path:reset()

Clears all path data. Warning: Don't call while rendering.

path:reset()

path:add(other, transform?)

Merges another path into this one.

path:add(other: Path, transform?: Mat2D)

path:measure()

Returns a PathMeasure for the entire path.

path:measure(): PathMeasure

path:contours()

Returns a ContourMeasure for the first contour.

path:contours(): ContourMeasure?

Operators

Length (#)

Returns the number of path commands.

local commandCount = #path

Example: Drawing a Triangle

local path = Path.new()
path:moveTo(Vector.xy(50, 0))
path:lineTo(Vector.xy(100, 100))
path:lineTo(Vector.xy(0, 100))
path:close()

See Also: PathMeasure, Renderer.drawPath


PathMeasure

Measures and manipulates paths.

Attributes

measure.length

Total length of the path across all contours. Type: number (read-only)

measure.isClosed

True only if the path has exactly one closed contour. Type: boolean (read-only)

Methods

measure:positionAndTangent(distance)

Returns the position and tangent at a distance along the path.

measure:positionAndTangent(distance: number): Vector, Vector

Returns: position, tangent (both Vector)

Example:

local measure = path:measure()
local pos, tan = measure:positionAndTangent(measure.length / 2)

measure:warp(point)

Transforms a point from "path space" coordinates to world coordinates along the path.

measure:warp(point: Vector): Vector

How it works:

  • X coordinate = Distance along the path (0 = start, measure.length = end)
  • Y coordinate = Perpendicular offset from the path centerline
    • Positive Y = Offset to the left of the path direction
    • Negative Y = Offset to the right of the path direction

Example: Text Along a Curve

-- Place points along a wavy path
local measure = curvePath:measure()

-- Point at 50% along path, centered on path
local center = measure:warp(Vector.xy(measure.length * 0.5, 0))

-- Point at 50% along path, 10 units to the left
local leftOffset = measure:warp(Vector.xy(measure.length * 0.5, 10))

-- Point at 50% along path, 10 units to the right
local rightOffset = measure:warp(Vector.xy(measure.length * 0.5, -10))

Use Cases:

  • Placing text or objects along a curved path
  • Creating parallel offset paths
  • Animating elements that follow a trajectory

measure:extract(start, end, dest, startWithMove?)

Extracts a segment into a destination path.

measure:extract(startDist: number, endDist: number, dest: Path, startWithMove?: boolean)

Example: Animated Line Drawing

local displayPath = Path.new()
measure:extract(0, measure.length * progress, displayPath, true)

See Also: ContourMeasure, Path.measure


ContourMeasure

Iterator for individual contours within a path. Use with path:contours() to iterate through multi-contour paths.

Attributes

contour.next

Next contour, or nil if this is the last. Type: ContourMeasure? (read-only)

Note: ContourMeasure provides iteration only. For length measurement and path manipulation, use PathMeasure instead.

Example: Iterating Contours

local contour = path:contours()
local count = 0
while contour do
count += 1
contour = contour.next
end
print("Path has", count, "contours")

See Also: PathMeasure


Paint

Defines how paths are rendered (fill/stroke, color, etc.).

Constructors

Paint.new()

Creates a paint with default settings.

Paint.new(): Paint

Paint.with(definition)

Creates a paint with multiple properties at once.

Paint.with(definition: PaintDefinition): Paint

PaintDefinition Type:

type PaintDefinition = {
style: ("fill" | "stroke")?, -- Rendering style (default: "fill")
color: Color?, -- Fill or stroke color
thickness: number?, -- Stroke width (stroke only)
cap: ("round" | "butt" | "square")?, -- Line endings (stroke only)
join: ("round" | "bevel" | "miter")?, -- Corner style (stroke only)
blendMode: BlendMode?, -- Compositing mode
feather: number?, -- Feathering amount
gradient: Gradient?, -- Applied gradient
}

All fields are optional. Unspecified fields use Paint defaults.

Example:

local stroke = Paint.with({
style = "stroke",
thickness = 3,
color = Color.rgb(255, 0, 102),
cap = "round",
join = "round"
})

Attributes

AttributeTypeDescription
style"fill" or "stroke"Rendering style
colorColorFill or stroke color
thicknessnumberStroke width (stroke only)
cap"round", "butt", "square"Line endings (stroke only)
join"round", "bevel", "miter"Corner style (stroke only)
blendModeBlendModeCompositing mode
feathernumberFeathering amount
gradientGradient?Applied gradient

Methods

paint:copy(overrides?)

Creates a copy with optional property overrides.

paint:copy(overrides?: PaintDefinition): Paint

Example:

local highlight = basePaint:copy({ color = Color.rgb(255, 255, 0) })

See Also: Gradient, Renderer.drawPath


Gradient

Color gradients for fills.

Constructors

Gradient.linear(from, to, stops)

Creates a linear gradient.

Gradient.linear(from: Vector, to: Vector, stops: {GradientStop}): Gradient

Example:

local gradient = Gradient.linear(
Vector.xy(0, 0),
Vector.xy(100, 0),
{
{ position = 0, color = Color.rgb(255, 0, 0) },
{ position = 1, color = Color.rgb(0, 0, 255) }
}
)

Gradient.radial(center, radius, stops)

Creates a radial gradient.

Gradient.radial(center: Vector, radius: number, stops: {GradientStop}): Gradient

GradientStop Type

type GradientStop = {
position: number, -- 0.0 to 1.0
color: Color
}

See Also: GradientStop


Renderer

Drawing commands and state management. Passed to draw() functions.

Methods

renderer:drawPath(path, paint)

Draws a path with the specified paint.

renderer:drawPath(path: Path, paint: Paint)

renderer:drawImage(image, sampler, blendMode, opacity)

Draws an image.

renderer:drawImage(image: Image, sampler: ImageSampler, blend: BlendMode, opacity: number)

renderer:drawImageMesh(image, vertices, uvs, indices)

Draws an image using mesh data (vertices, UVs, and triangle indices).

renderer:save()

Pushes the current state (transform, clip) onto the stack.

renderer:save()

renderer:restore()

Pops the last saved state. Always pair with save()!

renderer:restore()

renderer:transform(mat)

Applies a transformation to subsequent drawing.

renderer:transform(mat: Mat2D)

renderer:clipPath(path)

Restricts drawing to the path region until restore().

renderer:clipPath(path: Path)

Example: Drawing a Rotated Object

function draw(self, renderer)
renderer:save()
renderer:transform(Mat2D.withTranslation(self.x, self.y))
renderer:transform(Mat2D.withRotation(self.angle))
renderer:drawPath(self.path, self.paint)
renderer:restore()
end

Warning: Unbalanced save()/restore() calls cause rendering bugs in later frames.

See Also: Mat2D, Path, Paint

Next Steps