compact, portable and performant 2D vector graphics

ctx is a renderer and serialization format for 2D vector graphics, aiming for compatibility with HTML5 Canvas' 2D context. It leverages portable C code and auto-vectorization capabilities of modern compilers to target everything from microcontrollers to color managed RGB and CMYK compositing with 32bit floating point.

The motivation behind ctx was having a portable vector graphics library with a serialization protocol for use in a terminal emulator, while also covering the needs of GIMP and GEGL. To keep resource usage down; the prototyping platforms for ctx has been microcontrollers with SPI displays which is how it ended up in the firmwares of the following hacker-camp badges: card10, flow3r and tildagon.

ctx as an interactive 2D vector graphics protocol provides remote backends and process multiplexing integrated with a terminal emulator/window manager; providing an end-to-end vector rendering framework suitable for serial links. The serialization of the renderingT model is a superset of SVG path d attribute syntax. Internally (as well as for backends extending ctx; by appearing after the CTX_IMPLEMENTATION), a compact binary serialization of this syntax is used.

Pixel encodings supported range from 1bit to 32bit per pixel, in grayscale, RGB and CMYK. ctx can renders to lower bitdepth RGB332, RGB565 variants as well as 1,2 and 4 bit per pixel grayscale is handled.

arm32
tested on rp2040 and rpi2
aarch64
tested on a mediatek based chromebook
x86-64
Automatic runtime choice of 3 different levels of SIMD support.
tensilica
tested on esp32 and esp32s3
risc-v
tested on esp32c3
wasm
built with emscripten
?
if it is a 32bit or 64bit platform; with a C compiler it probably works.

The interactive backends of ctx are tailored towards low latency rendering of UIs where only a part of the screen changes, like editing text in a terminal or changing the hover state of a button. Ctx records the drawing commands to draw a frame, and before starting to draw computes a hash for a 6x5 grid dividing the buffer being rendered to. Horizontal chunks of tiles with new hashes compared to the previous frame are then scheduled for rendering on threads.

The ctx API still isn't fully covered by the rasterizer, in this feature comparison matrix, the protocol and rasterizer are separate columns.

.ctx-protocolctxcairoskiablend2d
GPU renderingNNYN
threaded renderingYNNY
automatic partial redrawsYNNN
event-handlingY
color management 8bitYNYN
color management floatPNNN
pcm-audioY
shadow blurYYNYN
inner shadowNNNYN
stroke-join-miterYNYYY
stroke-end-squareYPYYY
stroke-dashYYYYN
stroke-join-roundYYYYY
stroke-end-roundYYYYY
clippingYYYYN
compositing-groupsYPYYN
blending-modesYPYYY
textYYYYY
perspective-transform texturesYYN?N
perspective-transform pathsYYN?N
linear-gradientYYYYY
radial-gradientYPYYY
conic-gradientYYNYY
mesh-gradientNNY??
cmyk-gradientsYN
bilinear texturesYYYYY
nearest texturesYYYYY
Rendering targets
PDFPYY
RGBA YYYY
RGB30 NY?N
RGB332 YN?N
RGB565 YY?N
RGBA float YNNN
GRAY8 YYYY
GRAYA8 Y???
gray 1 bit YYNN
gray 2 bit YNNN
gray 4 bit YNNN
GRAY float YNNN
GRAYA float YNNN
CMYKAYNNN

Desired features specified for HTML5 canvas that are missing:

miter-limit
The stroker is currently always beveling strokes, fixing miter limit would also remove some currently hidden interesecting geometry on other parts of strokes.
focal point of radial gradient
correct result for shadow-blur
the SDF approximation is servicable in many cases but not correct.
filters
most importantly blur, but also brightness(),contrast(),grayscale(),hue-rotate(),invert(),opacity(),saturate(),sepia()
fontKerning
kerning is implemented in some of the font backends - but not ability to toggle on/off
direction
fontStretch
fontVariantCaps
letterSpacing
wordSpacing
textRendering
strokeText
Non HTML5-Canvas features desired, some for SVG capabilities:
stroke to path
for implementing strokeText
text along path baseline
text to path

ctx provides abstractions for event injection and dispatch. It provides hit-detection, this allows abstracting over multiple input devices/buttons with a mouse+keyboard abstraction. In the event method callback both absolute and local (At time of callback registration) coordinates are provided. Interactive ctx backends drive event delivery, if you are implementing the callback backend for microcontrollers and external displays you are expected to turn hardware events into interaction events.

The same API can also be used for writing applications that run inside the ctx terminal, which provides escape sequences that enable drawing 2D vector graphics both inline, and for full-window applications taking over the terminal using the ctx protocol, or even on webpages using webassembly, for now single threaded - and without the potential acceleration through reuse of the rasterizer of the HTML5 Canvas.

license and funding

ctx is available under LGPLv3+ you can encourage continued development of ctx and dissimilar technologies by financially supporting me, Øyvind Kolås who is doing independent pro-bono R&D through patreon and similar. If my income through such sources is above 4000USD per month for a year, or if someone does a one time payment of the equivalent amount for the time I invested in ctx over the last few years, ctx could become available under under the ISC license.