cairo.carp
June 24, 2026 ยท View on GitHub
Thin FFI bindings over the Cairo 2D graphics library for Carp.
The goal is to expose Cairo's C API with Carp-friendly naming (kebab-case, grouped under a single Cairo module), without layering a higher-level drawing model on top. Sketch-style primitives live in anima.carp.
Installation
Cairo must be installed on the system and discoverable via pkg-config:
brew install cairo # macOS
apt install libcairo2-dev # Debian / Ubuntu
Then load the library:
(load "git@github.com:carpentry-org/cairo.carp@0.2.0")
(or by local path during development).
Example
(load "cairo.carp")
(defn main []
(let-do [surf (Cairo.image-surface-create Cairo.format-argb32 200 200)
cr (Cairo.create surf)]
(Cairo.set-source-rgb cr 1.0 1.0 1.0)
(Cairo.paint cr)
(Cairo.set-source-rgb cr 0.0 0.0 0.0)
(Cairo.set-line-width cr 4.0)
(Cairo.move-to cr 20.0 20.0)
(Cairo.line-to cr 180.0 180.0)
(Cairo.stroke cr)
(ignore (Cairo.surface-write-to-png surf (cstr "out.png")))
(Cairo.destroy cr)
(Cairo.surface-destroy surf)))
Coverage
The binding currently covers the subset of Cairo that anima.carp needs, with some headroom:
- Surfaces: image / PDF / SVG creation, flush, finish, destroy, write-to-PNG, accessors for the raw image pixel buffer.
- Contexts: create, destroy, status, save / restore.
- Transforms: translate, rotate, scale, identity-matrix.
- Paths: new-path, new-sub-path, move-to, line-to, curve-to, the relative variants, arc, arc-negative, rectangle, close-path.
- Painting: stroke, fill, their
-preservevariants, paint, paint-with-alpha, clip, clip-preserve, reset-clip. - State: source RGB(A), line width / cap / join, operator, antialias, fill rule.
- Text:
select-font-face,set-font-size,show-text(Cairo's built-in toy text API).
Enums are exposed as distinct Carp types (CairoFormat, CairoLineCap, etc.) rather than raw Int, so type errors catch mix-ups at compile time.
Not yet bound: patterns, matrices as first-class values, set-dash, text-extents, font extents, scaled fonts, Cairo's lower-level path introspection. Easy to add.
Memory management
Cairo uses reference counting internally; this binding does not manage lifetimes for you. Every Cairo.create must be paired with a Cairo.destroy, and every *-surface-create with a Cairo.surface-destroy. See the Cairo manual for details.
Tests
carp -x test/cairo.carp
Builds a few surfaces, draws to them, writes PNG / SVG files to the working directory, and checks that they landed on disk. Run from the library root.