drawbot-skia is a Python implementation of the
DrawBot drawing API using
Skia as the rendering backend.
DrawBot is a friendly, Python-based way to make 2D graphics: posters, diagrams, type specimens, generated images, animations, PDFs, SVGs, and quick visual experiments. Classic DrawBot is a macOS app. This project is a package and command-line tool that lets similar DrawBot scripts run in a normal Python environment.
This fork focuses on broad DrawBot API coverage, visual test examples, and cross-platform use.
- Runs DrawBot-style Python scripts from the command line.
- Provides a Python module you can import in your own scripts.
- Draws shapes, paths, colors, gradients, text, formatted text, and images.
- Exports PNG, JPEG, PDF, SVG, animated GIF, and MP4 output.
- Supports
BezierPath,FormattedString, variable fonts, HarfBuzz shaping, manyImageObjectfilters, barcode generators, and visual docs examples. - Includes local
docs/andexamples/directories with rendered JPG previews that double as visual test fixtures.
The current API audit is tracked in API_GAP_AUDIT.md.
Install the package, then run a DrawBot script:
drawbot poster.py poster.pngA tiny script looks like this:
size(600, 400)
fill(0.95)
rect(0, 0, width(), height())
fill(0.1, 0.2, 0.35)
fontSize(64)
text("Hello Skia", (60, 190))
fill(0.95, 0.35, 0.15)
oval(420, 120, 110, 110)Save it as poster.py, then render it:
drawbot poster.py poster.pngThe CLI behaves like running a script in the DrawBot app: the drawing API names are injected into the script namespace, so the script does not need imports.
To use this fork as your installed drawbot-skia package:
python -m pip install --upgrade "drawbot-skia @ git+https://github.com/eliheuer/drawbot-skia.git"That installs the package and the drawbot command.
If you already installed the upstream package from PyPI and want this fork
instead, reinstall from the GitHub URL above. The package name and import path
are still drawbot-skia / drawbot_skia, so existing scripts that already use
drawbot_skia should keep the same imports.
For a local project:
uv venv
source .venv/bin/activate
uv pip install "drawbot-skia @ git+https://github.com/eliheuer/drawbot-skia.git"Run the CLI:
uv run drawbot poster.py poster.pngFor development from a clone:
git clone https://github.com/eliheuer/drawbot-skia.git
cd drawbot-skia
uv venv
source .venv/bin/activate
uv pip install -e ".[mp4]"
uv pip install -r requirements-dev.txtRun tests:
uv run pytest -qFor a local project:
python -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install "drawbot-skia @ git+https://github.com/eliheuer/drawbot-skia.git"Run the CLI:
drawbot poster.py poster.pngFor development from a clone:
git clone https://github.com/eliheuer/drawbot-skia.git
cd drawbot-skia
python -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install -e ".[mp4]"
python -m pip install -r requirements-dev.txtRun tests:
python -m pytest -qWindows note: skia-python requires 64-bit Python, so use a 64-bit Python
installer.
You can write scripts with explicit imports:
from drawbot_skia.drawbot import *
size(400, 300)
fill(1, 0, 0)
oval(100, 75, 200, 150)
saveImage("oval.png")Or use a module alias:
import drawbot_skia.drawbot as db
db.size(400, 300)
db.fill(0.1, 0.2, 0.4)
db.rect(40, 40, 320, 220)
db.saveImage("rectangle.png")Use the command-line runner when you want your script to look like a DrawBot app script with no imports:
drawbot script.py output.pngYou can pass more than one output file:
drawbot script.py output.png output.pdf output.svgRaster outputs can be rendered at a higher pixel scale:
drawbot --pixelScale 2 script.py output.jpgThis fork keeps the same package name, CLI command, and import path:
- package:
drawbot-skia - import path:
drawbot_skia - CLI command:
drawbot
If a script already uses upstream drawbot-skia, install this fork from GitHub
and keep the script as-is:
from drawbot_skia.drawbot import *Then run:
drawbot script.py output.pngMost simple DrawBot app scripts can be run directly with the CLI:
drawbot my-drawbot-script.py output.pdfIf you want to run the script with plain Python instead of the CLI, add this at the top:
from drawbot_skia.drawbot import *Then make sure the script calls saveImage(...):
saveImage("output.pdf")Some macOS DrawBot app APIs are intentionally not available in this cross-platform package. See Compatibility Notes.
The package is organized around a small set of core layers:
drawbot_skia.drawbot: a module-level DrawBot-style namespace for scripts.Drawing: the main stateful drawing object. It owns the current page, drawing state, text state, transforms, and export calls.runner: builds the script namespace used by thedrawbotCLI.document: records Skia pictures and exports them as PNG, JPEG, PDF, SVG, GIF, or MP4.gstate: stores fill, stroke, shadow, blend mode, text, and transform state.path: implementsBezierPathand path operations.formattedString: implements styled text runs.shapingandsegmenting: handle Unicode text shaping, bidi behavior, and text segmentation using HarfBuzz and related libraries.imageObject: implements DrawBot-styleImageObjectgenerators, filters, compositing, transitions, and barcode helpers.
At a high level:
- A script calls DrawBot-style functions such as
rect(),text(), orimage(). - Those calls update a
Drawingobject and draw into a Skia recording canvas. - Each page is stored as a Skia picture.
saveImage()or the CLI exports the recorded pages to the requested format.
If you are an AI coding agent or future maintainer, start with
AGENTS.md. It summarizes the project shape, verification
commands, common workflows, and current caveats. Use .agents/ for durable
task notes when work spans multiple turns or multiple agents.
Local docs live in docs/. Local examples live in
examples/. The examples are grouped after the main DrawBot
documentation categories:
- Shapes
- Colors
- Canvas
- Text
- Images
- Variables
- Quick Reference
The extra examples/showcase/ directory shows features this fork supports that
were missing or incomplete in the original upstream roadmap.
Regenerate the example previews with the default 2x pixel scale:
.venv/bin/python examples/render_examples.pyThe docs completion audit is in docs/completion-audit.md.
Clone the repo, install it in editable mode, and run tests:
git clone https://github.com/eliheuer/drawbot-skia.git
cd drawbot-skia
python -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install -e ".[mp4]"
python -m pip install -r requirements-dev.txt
python -m pytest -qRegenerate visual examples:
.venv/bin/python examples/render_examples.pyThe original roadmap items are now broadly implemented in this fork:
- basic shapes and colors
BezierPath- transformations
- text and
textBox() - variable fonts
- HarfBuzz shaping
- OpenType features
- PNG, JPEG, PDF, SVG, MP4, and animated GIF export
FormattedString- many
ImageObjectAPIs - static DrawBot API method coverage, with behavior caveats below
The detailed parity status is tracked in API_GAP_AUDIT.md.
This project is cross-platform and Skia-backed. It is not the macOS DrawBot app, and it does not use CoreText, Core Image, AppKit, or PDFKit internally.
Important differences:
- Text layout and shaping are implemented in this package using Skia,
HarfBuzz, FontTools, and related libraries.
textBox()andFormattedStringare available, but output should not be expected to match macOS DrawBot/CoreText pixel-for-pixel. - Many
ImageObjectmethods are Pillow-backed compatibility implementations rather than Core Image-equivalent filters. They are useful and tested, but exact Core Image pixel parity should be treated as method-by-method follow-up work. - macOS bridge APIs are intentionally out of scope for this package. These names
exist as explicit compatibility stubs and raise
DrawbotError:Variable(),pdfImage(),printImage(),FormattedString.getNSObject(),BezierPath.getNSBezierPath(), andBezierPath.setNSBezierPath(). BezierPath.traceImage()follows DrawBot's external-tool model. It requires bothmkbitmapandpotraceonPATH. On macOS, install them withbrew install potrace. On Debian/Ubuntu Linux, install them withapt install potrace.
Some improvements specific to this fork include focused ImageObject drawing,
barcode generators, alpha-aware mask behavior, broader transition/distortion
approximations, link annotations for SVG/PDF, and radial gradient parity for
DrawBot's radius and point controls.
This project uses the Apache License 2.0. See LICENSE.txt.