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

Measurement and manipulation for individual contours within a path. ContourMeasure has all the capabilities of PathMeasure plus the ability to iterate through multi-contour paths via the next property.

Attributes

contour.length

Total length of this contour. Type: number (read-only)

contour.isClosed

True if this contour is closed. Type: boolean (read-only)

contour.next

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

Methods

contour:positionAndTangent(distance)

Returns the position and tangent at a distance along this contour.

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

contour:warp(point)

Transforms a point from "path space" coordinates to world coordinates along this contour. See PathMeasure.warp for details.

contour:warp(point: Vector): Vector

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

Extracts a segment of this contour into a destination path.

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

Example: Iterating Contours

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

Example: Measuring Each Contour

local contour = path:contours()
while contour do
local pos, tan = contour:positionAndTangent(contour.length / 2)
print("Midpoint:", pos.x, pos.y)
contour = contour.next
end

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, sampler, vertices, uvs, triangles, blendMode, opacity)

Draws an image mapped onto a triangle mesh.

renderer:drawImageMesh(image: Image, sampler: ImageSampler,
vertices: VertexBuffer, uvs: VertexBuffer, triangles: TriangleBuffer,
blendMode: BlendMode, opacity: number)

When to use: Advanced image warping onto custom geometry, cloth simulation, terrain rendering.

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