Drawing in Sesi
std/draw is Sesi's built-in module for creating SVG graphics and raster pixel art — no external libraries needed.
---
Importing the Module
allow "std/draw" in as <alias>
The name after as is your choice — any identifier works:
allow "std/draw" in as Draw // conventional
allow "std/draw" in as canvas // also fine
allow "std/draw" in as d // also fine
The examples below use Draw as a readable convention.
---
Drawing Shapes
Every draw call appends a shape to an internal buffer. Nothing is rendered or saved until you call render or save_svg. This only applies to SVG output; pixel-based drawings are handled differently. Do not call save_png for SVG shapes — only use it when using Draw.pixel(), Draw.pixel_grid(), or Draw.pixel_<shape>() functions.
---
Rectangle — Draw.rect
Draw.rect(x, y, width, height, fill)
| Parameter | Type | Description | |
|---|---|---|---|
x |
number |
Left edge (pixels) | |
y |
number |
Top edge (pixels) | |
width |
number |
Width in pixels | |
height |
number |
Height in pixels | |
fill |
string |
CSS color (name, hex, rgb, etc) |
allow "std/draw" in as Draw
Draw.rect(10, 10, 80, 50, "steelblue")
Draw.rect(20, 70, 60, 20, "#ff6347")
---
Circle — Draw.circle
Draw.circle(x, y, radius, fill)
| Parameter | Type | Description | |
|---|---|---|---|
x |
number |
Center X coordinate | |
y |
number |
Center Y coordinate | |
radius |
number |
Radius in pixels | |
fill |
string |
CSS color |
allow "std/draw" in as Draw
Draw.circle(50, 50, 40, "crimson")
Draw.circle(150, 50, 20, "gold")
---
Line — Draw.line
Draw.line(x1, y1, x2, y2, stroke)
| Parameter | Type | Description | |
|---|---|---|---|
x1 |
number |
Start X | |
y1 |
number |
Start Y | |
x2 |
number |
End X | |
y2 |
number |
End Y | |
stroke |
string |
CSS color for the line |
allow "std/draw" in as Draw
Draw.line(0, 0, 200, 200, "white")
Draw.line(200, 0, 0, 200, "white") // X pattern
---
Text — Draw.text
Draw.text(x, y, content, size, fill)
| Parameter | Type | Description | |
|---|---|---|---|
x |
number |
Left edge of the text | |
y |
number |
Baseline Y position | |
content |
string |
The text to render | |
size |
number |
Font size in pixels | |
fill |
string |
CSS color |
allow "std/draw" in as Draw
Draw.text(10, 30, "Hello, Sesi", 24, "white")
Draw.text(10, 60, "SVG is easy", 16, "#aaa")
---
Clearing the Buffer — Draw.clear
Draw.clear()
Wipes everything in the drawing buffer. Use this to reset between separate drawings in the same script:
allow "std/draw" in as Draw
Draw.circle(50, 50, 40, "red")
Draw.clear() // start fresh
Draw.rect(10, 10, 80, 80, "blue") // only this will appear
Draw.save_svg("output.svg", 100, 100)
---
Getting the SVG String — Draw.render
Draw.render(width, height) -> string
Flushes the buffer and returns the complete SVG document as a string. The buffer is not cleared afterward.
allow "std/draw" in as Draw
Draw.rect(0, 0, 200, 100, "navy")
Draw.text(10, 60, "Sesi", 40, "white")
let svg = Draw.render(200, 100)
show svg
You can pass the returned string to write_file or embed it in HTML:
let svg = Draw.render(400, 300)
let page = "<html><body>" + svg + "</body></html>"
write_file("preview.html", page)
---
Saving to a File — Draw.save_svg
Draw.save_svg(path, width, height)
Renders the buffer and writes the SVG directly to path. Equivalent to calling render then write_file.
allow "std/draw" in as Draw
Draw.rect(0, 0, 400, 300, "#1a1a2e")
Draw.circle(200, 150, 100, "#e94560")
Draw.text(130, 160, "Sesi Draw", 28, "white")
Draw.save_svg("poster.svg", 400, 300)
show "Saved poster.svg"
---
Raster Pixel Drawing
Draw.pixel and Draw.pixel_<shape> functions write directly to a raster pixel buffer that is separate from the SVG shape buffer. Calling Draw.save_png encodes those raster pixels into a true-color RGBA PNG file.
---
Single Pixel — Draw.pixel
Draw.pixel(x, y, color)
| Parameter | Type | Description | |
|---|---|---|---|
x |
number |
Integer X coordinate | |
y |
number |
Integer Y coordinate | |
color |
string |
Color (name, #hex, rgb, rgba) |
allow "std/draw" in as Draw
Draw.pixel(0, 0, "#ff4d6d")
Draw.pixel(1, 0, "#ffd166")
Draw.pixel(0, 1, "rgba(6, 214, 160, 0.5)")
Draw.pixel(1, 1, "#118ab2")
Draw.save_png("pixels.png", 2, 2)
---
Pixel Grid — Draw.pixel_grid
For pixel art, a palette-indexed grid is compact. String rows use characters as palette keys, expanding each grid cell by scale:
Draw.pixel_grid(grid, palette, scale, x, y)
| Parameter | Type | Description | |
|---|---|---|---|
grid |
array |
Array of row strings or character arrays | |
palette |
object |
Mapping of characters to color strings | |
scale |
number |
Pixel scale multiplier per grid cell | |
x |
number |
Top-left X offset on canvas | |
y |
number |
Top-left Y offset on canvas |
let palette = {
".": "#111a38",
"X": "#56d9e9"
}
let grid = [
".XX.",
"X..X",
"X..X",
".XX."
]
Draw.pixel_grid(grid, palette, 128)
Draw.save_png("grid.png", 512, 512)
---
Pixel Rectangle — Draw.pixel_rect
Rasterizes a filled or outline rectangle into the pixel buffer.
Draw.pixel_rect(x, y, w, h, color, filled)
| Parameter | Type | Description | |
|---|---|---|---|
x |
number |
Top-left X coordinate | |
y |
number |
Top-left Y coordinate | |
w |
number |
Width in pixels | |
h |
number |
Height in pixels | |
color |
string |
Fill/stroke color | |
filled |
boolean |
true for solid fill, false for outline |
allow "std/draw" in as Draw
Draw.pixel_rect(10, 10, 80, 50, "#e94560", true)
Draw.pixel_rect(20, 20, 60, 30, "#ffffff", false)
Draw.save_png("pixel_rect.png", 100, 100)
---
Pixel Circle — Draw.pixel_circle
Rasterizes a filled or outline circle into the pixel buffer using Euclidean distance.
Draw.pixel_circle(cx, cy, r, color, filled)
| Parameter | Type | Description | |
|---|---|---|---|
cx |
number |
Center X coordinate | |
cy |
number |
Center Y coordinate | |
r |
number |
Radius in pixels | |
color |
string |
Fill/stroke color | |
filled |
boolean |
true for solid fill, false for outline |
allow "std/draw" in as Draw
Draw.pixel_circle(50, 50, 30, "#00f0ff", true)
Draw.save_png("pixel_circle.png", 100, 100)
---
Pixel Line — Draw.pixel_line
Rasterizes a line between two points into the pixel buffer using Bresenham's algorithm.
Draw.pixel_line(x1, y1, x2, y2, color)
| Parameter | Type | Description | |
|---|---|---|---|
x1 |
number |
Start X coordinate | |
y1 |
number |
Start Y coordinate | |
x2 |
number |
End X coordinate | |
y2 |
number |
End Y coordinate | |
color |
string |
Line color |
allow "std/draw" in as Draw
Draw.pixel_line(0, 0, 99, 99, "#ff0077")
Draw.save_png("pixel_line.png", 100, 100)
---
Pixel Ellipse — Draw.pixel_ellipse
Rasterizes an ellipse into the pixel buffer.
Draw.pixel_ellipse(cx, cy, rx, ry, color, filled)
| Parameter | Type | Description | |
|---|---|---|---|
cx |
number |
Center X coordinate | |
cy |
number |
Center Y coordinate | |
rx |
number |
Horizontal radius | |
ry |
number |
Vertical radius | |
color |
string |
Fill/stroke color | |
filled |
boolean |
true for solid fill, false for outline |
allow "std/draw" in as Draw
Draw.pixel_ellipse(50, 50, 40, 20, "#ffb703", true)
Draw.save_png("pixel_ellipse.png", 100, 100)
---
Pixel Polygon — Draw.pixel_polygon
Rasterizes an arbitrary closed polygon using scanline fill.
Draw.pixel_polygon(points, color, filled)
| Parameter | Type | Description | |
|---|---|---|---|
points |
array or string |
Point coordinate pairs (e.g., [[0,0],[40,0],[20,40]] or "0,0 40,0 20,40") |
|
color |
string |
Fill/stroke color | |
filled |
boolean |
true for solid fill, false for outline |
allow "std/draw" in as Draw
Draw.pixel_polygon([[10,10], [90,10], [50,90]], "#06d6a0", true)
Draw.save_png("pixel_polygon.png", 100, 100)
---
Pixel Triangle — Draw.pixel_triangle
Rasterizes a triangle into the pixel buffer.
Draw.pixel_triangle(x1, y1, x2, y2, x3, y3, color, filled = true)
| Parameter | Type | Description | |
|---|---|---|---|
x1, y1 |
number |
Point 1 coordinates | |
x2, y2 |
number |
Point 2 coordinates | |
x3, y3 |
number |
Point 3 coordinates | |
color |
string |
Fill/stroke color | |
filled |
boolean |
true for solid fill, false for outline |
allow "std/draw" in as Draw
Draw.pixel_triangle(10, 80, 50, 10, 90, 80, "#ff4d6d", true)
Draw.save_png("pixel_triangle.png", 100, 100)
---
Pixel Star — Draw.pixel_star
Rasterizes a multi-pointed star shape into the pixel buffer.
Draw.pixel_star(cx, cy, spikes, outerRadius, innerRadius, color, filled = true)
| Parameter | Type | Description | |
|---|---|---|---|
cx, cy |
number |
Center coordinates | |
spikes |
number |
Number of star points (e.g. 5) |
|
outerRadius |
number |
Outer point radius | |
innerRadius |
number |
Inner point radius | |
color |
string |
Fill/stroke color | |
filled |
boolean |
true for solid fill, false for outline |
allow "std/draw" in as Draw
Draw.pixel_star(50, 50, 5, 40, 18, "#ffd166", true)
Draw.save_png("pixel_star.png", 100, 100)
---
Pixel Ring — Draw.pixel_ring
Rasterizes a ring / annulus band into the pixel buffer.
Draw.pixel_ring(cx, cy, radius, thickness, color)
| Parameter | Type | Description | |
|---|---|---|---|
cx, cy |
number |
Center coordinates | |
radius |
number |
Outer radius | |
thickness |
number |
Band thickness in pixels | |
color |
string |
Ring color |
allow "std/draw" in as Draw
Draw.pixel_ring(50, 50, 40, 8, "#118ab2")
Draw.save_png("pixel_ring.png", 100, 100)
---
Pixel Arc — Draw.pixel_arc
Rasterizes a circular arc segment in degrees into the pixel buffer.
Draw.pixel_arc(cx, cy, radius, startAngle, endAngle, color)
| Parameter | Type | Description | |
|---|---|---|---|
cx, cy |
number |
Center coordinates | |
radius |
number |
Arc radius | |
startAngle |
number |
Start angle in degrees | |
endAngle |
number |
End angle in degrees | |
color |
string |
Arc line color |
allow "std/draw" in as Draw
Draw.pixel_arc(50, 50, 35, 0, 180, "#7209b7")
Draw.save_png("pixel_arc.png", 100, 100)
---
Pixel Bezier Curve — Draw.pixel_bezier
Rasterizes a quadratic Bezier curve into the pixel buffer.
Draw.pixel_bezier(x1, y1, cx, cy, x2, y2, color)
| Parameter | Type | Description | |
|---|---|---|---|
x1, y1 |
number |
Start point coordinates | |
cx, cy |
number |
Control point coordinates | |
x2, y2 |
number |
End point coordinates | |
color |
string |
Curve line color |
allow "std/draw" in as Draw
Draw.pixel_bezier(10, 90, 50, 10, 90, 90, "#4cc9f0")
Draw.save_png("pixel_bezier.png", 100, 100)
---
Pixel Text — Draw.pixel_text
Rasterizes text using a built-in bitmap pixel font into the pixel buffer.
Draw.pixel_text(x, y, text, color, scale = 1)
| Parameter | Type | Description | |
|---|---|---|---|
x |
number |
Left X position | |
y |
number |
Top Y position | |
text |
string |
Text string to render | |
color |
string |
Text color | |
scale |
number |
Pixel scale multiplier per glyph cell |
allow "std/draw" in as Draw
Draw.pixel_text(10, 10, "PIXEL ART", "#f72585", 2)
Draw.save_png("pixel_text.png", 200, 50)
---
Saving PNG Output — Draw.save_png
Draw.save_png(path, width, height, background = "transparent")
Encodes all raster pixels in the buffer to a PNG image file. Coordinates are floored to integers. A later call at the same coordinate replaces the earlier pixel color. Draw.clear() resets both the SVG and raster pixel buffers.
---
Key Differences When Working With Full Resolutions:
- Canvas Allocation:
Draw.save_png(path, width, height, "transparent")instructs the raster engine to write a complete width×height viewport - Scale Multipliers:
- Draw.pixel_text(x, y, text, color, scale): Using scale = 2 or scale = 3 scales bitmap font glyphs up so they remain legible on large canvases.
- Draw.pixel_grid(grid, palette, scale): When using palette grids on an HD canvas, set scale (e.g., 32, 64, or 128) so that character cells map to sizable multi-pixel blocks rather than single 1px dots.
- Primitive Sizing: Coordinates for
pixel_polygon,pixel_triangle,pixel_star,pixel_circle, andpixel_rectmust scale with the destination dimensions
---
Composing Multiple Shapes
Shapes are layered in the order they are added, so earlier calls appear behind later ones:
allow "std/draw" in as Draw
// Background
Draw.rect(0, 0, 300, 200, "#0f0f23")
// Sun
Draw.circle(250, 50, 40, "#ffd700")
// Ground
Draw.rect(0, 150, 300, 50, "#2d6a4f")
// Tree trunk
Draw.rect(135, 110, 30, 60, "#6b4226")
// Tree top
Draw.circle(150, 100, 40, "#52b788")
// Label
Draw.text(10, 190, "A Sesi landscape", 14, "#ccc")
Draw.save_svg("landscape.svg", 300, 200)
---
Advanced Features (Gradients, Animations, Options)
Sesi's drawing module has built-in support for:
- Attributes / Options: You can pass a dictionary of attributes as the final argument to shape rendering functions to add CSS classes, IDs, strokes, and more.
- Gradients: Define linear/radial gradients inside the
<defs>element usingDraw.gradient. - CSS Keyframe Animations: Inject custom
@keyframesstyling into the generated SVG header usingDraw.style. - Complex Shapes: Draw curves and lines via
ellipse,polygon, andpath. - Raw Elements: Inject arbitrary SVG markup tags directly using
Draw.raw.
Example: Animated Vector Art with Gradients
allow "std/draw" in as Draw
// 1. Define a radial gradient for a neon glow
Draw.gradient("radial", "glow_grad", [
{offset: "0%", color: "#ff00ff"},
{offset: "100%", color: "transparent"}
])
// 2. Define standard CSS animations for pulsating and spinning
Draw.style("
@keyframes heartbeat {
0% { transform: scale(1); }
50% { transform: scale(1.15); }
100% { transform: scale(1); }
}
.pulse {
animation: heartbeat 2s infinite ease-in-out;
transform-origin: 200px 200px;
}
")
// 3. Draw using options to bind classes and gradients
Draw.rect(0, 0, 400, 400, "#0a0018")
Draw.circle(200, 200, 100, "url(#glow_grad)", {class: "pulse"})
Draw.ellipse(200, 200, 50, 25, "#00ffff")
Draw.save_svg("neon.svg", 400, 400)
---
Error Handling
Wrap file-saving calls in try/catch to handle path or permission errors:
allow "std/draw" in as Draw
Draw.rect(0, 0, 100, 100, "teal")
try {
Draw.save_svg("output/drawing.svg", 100, 100)
show "Saved successfully"
} catch (err) {
show "Draw error:" err
}
---
Quick Reference
allow "std/draw" in as Draw
// Setup & Formatting
Draw.gradient(type, id, stops, options = {})
Draw.style(cssText)
Draw.raw(svgCode)
// Shapes (all accept optional custom attributes dictionary)
Draw.rect(x, y, width, height, fill, options = {})
Draw.circle(x, y, radius, fill, options = {})
Draw.line(x1, y1, x2, y2, stroke, options = {})
Draw.text(x, y, content, size, fill, options = {})
Draw.ellipse(cx, cy, rx, ry, fill, options = {})
Draw.polygon(points, fill, options = {})
Draw.path(d, fill, options = {})
// Buffer actions
Draw.clear()
let svg = Draw.render(width, height)
Draw.save_svg("output.svg", width, height)
// Raster pixels
Draw.pixel(x, y, color)
Draw.pixel_grid(grid, palette, scale = 1, x = 0, y = 0)
Draw.pixel_rect(x, y, w, h, color, filled = true)
Draw.pixel_circle(cx, cy, r, color, filled = true)
Draw.pixel_line(x1, y1, x2, y2, color)
Draw.pixel_ellipse(cx, cy, rx, ry, color, filled = true)
Draw.pixel_polygon(points, color, filled = true)
Draw.pixel_triangle(x1, y1, x2, y2, x3, y3, color, filled = true)
Draw.pixel_star(cx, cy, spikes, outerRadius, innerRadius, color, filled = true)
Draw.pixel_ring(cx, cy, radius, thickness, color)
Draw.pixel_arc(cx, cy, radius, startAngle, endAngle, color)
Draw.pixel_bezier(x1, y1, cx, cy, x2, y2, color)
Draw.pixel_text(x, y, text, color, scale = 1)
Draw.save_png("output.png", width, height, "transparent")
---