Draw Module

The nib.draw module provides declarative drawing commands for the Canvas view. Commands describe shapes, images, text, and paths that are rendered via Core Graphics on macOS with GPU acceleration.

To render a path as a view instead of on a Canvas, use Path & Shape. Comparison below.

All drawing is performed through command objects that are passed to canvas.draw(), canvas.append(), or provided as the commands parameter on the Canvas constructor. Commands are dataclasses and can be freely created, stored, and reused.

Sections

Section Description
Primitives Shape commands: Rect, Circle, Ellipse, Line, Arc, Path, Polygon, BezierPath, Points, Shadow, Fill, ColorFill.
Paint & Gradients Paint styling class, PaintStyle, StrokeCap, StrokeJoin enums, and gradient fills: LinearGradient, RadialGradient, SweepGradient.
Path Elements Typed path elements for BezierPath: MoveTo, LineTo, CubicTo, QuadraticTo, Close, ArcTo, Oval, SubPath.
Image & Text Image (raw bytes) and Text drawing commands with font and alignment support.

Path & Shape: the view-level path API

nib.Path has the same operations as BezierPath. nib.Shape renders it as a SwiftUI view instead of a canvas command. Use Shape when the drawing is part of the layout:

Use Canvas for absolute pixel coordinates, many commands per frame, images and text, pan gestures, or append() / clear() at runtime.

nib.Shape + nib.Path nib.Canvas + nib.draw
Result A view in the layout A fixed-size drawing surface
Coordinates view_box units, scaled to the frame Points on the canvas
Styling View modifiers, gradient views Paint, nib.draw gradients, Shadow, Blur
Updates Rebuild the view draw(), append(), clear()
Input None Pan gestures
Images and text No nib.draw.Image, nib.draw.Text

Operation mapping:

nib.Path method nib.draw path element
move_to(x, y) MoveTo(x, y)
line_to(x, y) LineTo(x, y)
curve_to(x, y, control1, control2) CubicTo(cp1x, cp1y, cp2x, cp2y, x, y)
quad_curve_to(x, y, control) QuadraticTo(cp1x, cp1y, x, y)
arc(center, radius, start_angle, end_angle, clockwise) PathArc(x, y, width, height, start_angle, sweep_angle)
close() Close()
add_rect(x, y, width, height) PathRect(x, y, width, height)
add_rounded_rect(x, y, width, height, corner_radius) PathRect(x, y, width, height, border_radius)
add_ellipse(x, y, width, height) Oval(x, y, width, height)
add_circle(center_x, center_y, radius) Oval(cx - r, cy - r, 2 * r, 2 * r)
ArcTo, SubPath have no nib.Path equivalent

Same triangle, both APIs:

import nib

# As a view: scales to its frame and takes modifiers
nib.Shape(
    path=nib.Path().move_to(50, 0).line_to(100, 100).line_to(0, 100).close(),
    view_box=(100, 100),
    fill="#3B82F6",
    width=48,
    height=48,
    shadow_radius=4,
)

# On a canvas: absolute points, redrawn on demand
canvas = nib.Canvas(width=120, height=120)
canvas.draw([
    nib.draw.BezierPath(
        elements=[
            nib.draw.MoveTo(50, 0),
            nib.draw.LineTo(100, 100),
            nib.draw.LineTo(0, 100),
            nib.draw.Close(),
        ],
        fill="#3B82F6",
    ),
])

Quick example

import nib

def main(app: nib.App):
    canvas = nib.Canvas(width=400, height=300, background_color="#1e1e1e")
    canvas.draw([
        # Rounded rectangle with gradient fill
        nib.draw.Rect(
            x=20, y=20, width=160, height=100,
            fill=nib.draw.LinearGradient(
                start=(20, 20), end=(180, 120),
                colors=["#6366F1", "#EC4899"],
            ),
            corner_radius=12,
        ),
        # Circle with radial gradient
        nib.draw.Circle(
            cx=300, cy=80, radius=50,
            fill=nib.draw.RadialGradient(
                center=(300, 80), radius=50,
                colors=["#FBBF24", "#F97316"],
            ),
        ),
        # Connecting line
        nib.draw.Line(x1=180, y1=70, x2=250, y2=80, stroke="#ffffff", stroke_width=2),
        # Label
        nib.draw.Text("Dashboard", x=20, y=260, fill="#ffffff"),
    ])

    app.build(canvas)

nib.run(main)

Color values

All color parameters in draw commands accept either:

  • Hex strings: "#FF0000", "#ff0000", "FF0000"
  • nib.Color objects: nib.Color.RED, nib.Color(hex="#FF0000")

Gradient fills (LinearGradient, RadialGradient, SweepGradient) can be used in place of solid colors on any fill parameter.