Library / SDK
sammycage/plutovg avatar
sammycage/plutovg

PlutoVG draws paths, text and gradients from C without a graphics toolkit

Tiny 2D vector graphics library in C

528 stars71 forksCMIT

At a glance

What is it?
PlutoVG is a standalone 2D vector graphics library in C that covers path filling, stroking and dashing, solid, gradient and texture paints, fonts and text, clipping and compositing, transformations and images, and it can be built with either Meson or CMake.
Who is it for?
PlutoVG fits a C project that needs to render vector output without linking a windowing system or a rendering framework, such as a tool that writes SVG or PNG, a firmware UI, or a service that turns geometry into an image. It is the wrong tool if you need to display anything on screen, since it rasterises into a surface rather than driving a display, and the wrong tool if you want to parse SVG, since that is the job of the sibling projects built on it.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 99 days ago.
What is it written in?
Mainly C, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 20, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What the feature list actually covers

PlutoVG is a standalone 2D vector graphics library in C, and the feature list in the README is short enough to read as a specification. Path filling, stroking and dashing. Solid, gradient and texture paints. Fonts and texts. Clipping and compositing. Transformations. Images.

That is the scope of a real 2D rasteriser rather than a helper library, and the phrase standalone is doing work. There is no windowing system in the dependency list, no GPU context and no image loading library required. The output is a surface in memory, and the surface is what you write out.

The consequence is that PlutoVG is a rendering back end, not a graphics stack. It draws the picture; it does not show it to you, it does not read your scene description, and it does not own a window. That separation is exactly what makes it useful in a build script, a server side image generator or an embedded target, and exactly what makes it the wrong thing to reach for when you want to draw an interactive window.

The topics confirm the framing, listing 2d, canvas, graphics, svg and vector.

The API is a surface, a canvas, and a sequence of drawing calls

The example in the README is the whole library in one file, and it reads like a typical immediate-mode 2D API. You create a surface with a width and a height, create a canvas on top of it, draw into the canvas, write the surface to a PNG, then destroy both.

c
#include <plutovg.h>

int main(void)
{
    const int width = 150;
    const int height = 150;

The naming convention is consistent and readable. A canvas is saved before a group of operations and restored afterwards, which is the transform stack, and plutovg_canvas_arc draws a circular segment, plutovg_canvas_set_rgb sets the paint colour, plutovg_canvas_fill_preserve fills the current path and keeps it, and plutovg_canvas_stroke strokes it. The line width is set separately with plutovg_canvas_set_line_width.

The fill and preserve pairing is the detail worth noticing, because it is the difference between one call and two. A path can be filled, stroked, or filled and then stroked, and preserving the path after a fill is what lets a single arc be both the yellow face and the black outline in the example.

Arcs, angles and the shape of the example

The example is a smiley face, and the geometry is a reasonable tour of what the path API does. The face is an arc with a radius of 70 drawn from zero to PLUTOVG_TWO_PI, so a full circle, and the mouth is an arc from zero to PLUTOVG_PI, so half a circle.

c
    plutovg_canvas_save(canvas);
    plutovg_canvas_arc(canvas, center_x, center_y, face_radius, 0, PLUTOVG_TWO_PI, 0);
    plutovg_canvas_set_rgb(canvas, 1, 1, 0);
    plutovg_canvas_fill_preserve(canvas);
    plutovg_canvas_set_rgb(canvas, 0, 0, 0);
    plutovg_canvas_set_line_width(canvas, 5);
    plutovg_canvas_stroke(canvas);
    plutovg_canvas_restore(canvas);

The last argument of the arc call is the direction flag, and the constant PLUTOVG_TWO_PI shows that the library exposes its own angle constants rather than expecting you to define pi.

The eyes are two arcs in one path, drawn in a single fill call, which is a small demonstration of the path model. Two separate arc calls accumulate into one path, and one fill draws both. The eye positions are computed from a centre with an x and y offset, so the face is parametric and the numbers in the file are the whole geometry.

At the end the surface is written to a PNG file, which is the output path that makes the library useful in a script.

Two build systems, one library

Installation is offered through Meson or CMake, and both are documented with the same four step shape: clone, change directory, configure a build directory, build, install.

With Meson:

bash
git clone https://github.com/sammycage/plutovg.git
cd plutovg
meson setup build
meson compile -C build
meson install -C build

With CMake:

bash
git clone https://github.com/sammycage/plutovg.git
cd plutovg
cmake -B build .
cmake --build build
cmake --install build

The repository supports both, with a CMakeLists.txt, a cmake directory, a meson.build and a meson_options.txt at the top level. The examples directory has its own CMakeLists.txt and meson.build alongside smiley.c, which is the file the README's example corresponds to, so the example is built as part of the project rather than being an isolated snippet.

Offering both build systems is a small decision with a real audience, since Meson is what many Linux distributions and cross-compilation setups use, and CMake is what most existing C projects already have in place. Shipping both means neither is a second class citizen.

The projects built on it, and what that says about its role

The README lists two projects that use PlutoVG, and both are by the same author. LunaSVG and PlutoSVG, the latter presumably the SVG counterpart.

That relationship is the clearest statement of what PlutoVG is and is not. A rasteriser draws a picture that has already been described. An SVG parser reads a document that describes a picture. The two are separate jobs, and a stack that does both needs one component for each. PlutoVG is the drawing half, and the fact that two sibling projects exist to feed it means the layering is intentional rather than accidental.

For an adopter, this has a practical consequence. If your input is SVG, the question is not which vector library to use but which parser to pair with the rasteriser, and the author has already published one. If your input is your own geometry, a path and a colour, PlutoVG is directly what you want and there is no document layer to think about.

It is also worth noticing that the whole family is by one person, with a companion project for reverse engineering rather than rasterising. The scope is deliberately narrow, and the sibling projects show the boundaries.

Where PlutoVG is the wrong choice

The first limit is the output. Everything the library produces ends up in a surface you then write to a file. It does not draw to a display, it does not blit to a window, and it does not talk to a GPU. A desktop application or a game needs a rendering back end, and a 2D canvas library for that is a different dependency with a different set of requirements.

The second is that there is no document layer. No SVG parsing, no scene graph, no retained object model, no layout. If your program needs to read a drawing described in a file, you need a parser on top, and the structure of that relationship is up to you.

The third is the input side of rasterisation, which is where this class of library quietly limits you. The feature list mentions textures, and it mentions fonts and texts, and both of those pull in the parts of a graphics stack that are hardest to keep small. Font handling in particular means finding font files, and that is a platform question rather than a geometry question. A library that claims to be tiny and still does text is making a trade, and you should find out what it costs on your platform before you design around it.

The fourth is scale. This is a software rasteriser in C with no hardware acceleration, so the cost of a large path or a lot of text is paid on the CPU. For charts, diagrams and generated artwork that is a non-issue, and for a full screen of animated vector content it is not.

Licence, releases and the state of the project

The library is released under the MIT Licence, with the LICENSE file at the root of the repository and the licence badge in the README.

The release history is steady. The recent versions are v1.3.3 from 2026-05-18, v1.3.2 from 2025-11-18 and v1.3.1 from 2025-09-14, and the last push to the repository was on 2026-07-16, with the repository not archived. A version 1.x with regular minor releases over that period is the profile of a library whose API has settled and whose remaining work is refinement and fixes.

The repository is a conventional C project layout. There is an include directory for the public header, a source directory for the implementation, a cmake directory for the CMake build support, the examples directory, and the two build files. The public surface is a single header, plutovg.h, which is what the example includes.

The README also carries badges for the build workflow, the licence, the latest release and a code quality service, and the smiley.png output of the example sits at the root of the repository so the rendered result is visible without building anything.

Editorial conclusion

PlutoVG fits a C project that needs to render vector output without linking a windowing system or a rendering framework, such as a tool that writes SVG or PNG, a firmware UI, or a service that turns geometry into an image. It is the wrong tool if you need to display anything on screen, since it rasterises into a surface rather than driving a display, and the wrong tool if you want to parse SVG, since that is the job of the sibling projects built on it. Before you adopt it, check three things: that you can build it with either Meson or CMake on your platform, that the text rendering works with the fonts you have available, since fonts and texts are a listed feature and font handling is where a rasteriser meets the operating system, and that the licence suits you, which is MIT and permissive. The current release is v1.3.3 from 2026-05-18, the last push was on 2026-07-16, and the repository publishes GitHub releases.

Frequently asked questions

What can PlutoVG draw?

The feature list covers path filling, stroking and dashing, solid, gradient and texture paints, fonts and texts, clipping and compositing, transformations, and images. The example in the README draws a smiley from arcs, fills and strokes.

How do I build and install PlutoVG?

With Meson, run `meson setup build`, `meson compile -C build` and `meson install -C build` after cloning, or with CMake, run `cmake -B build .`, `cmake --build build` and `cmake --install build`. The repository ships both build systems.

Does PlutoVG parse SVG files?

No, it is a rasteriser. The README lists two sibling projects that use it, LunaSVG and PlutoSVG, which are the document and parsing side, while PlutoVG does the drawing into a surface you can write to a PNG.

What is the API shape of PlutoVG?

You create a surface, create a canvas on it, and issue drawing calls such as plutovg_canvas_arc, plutovg_canvas_set_rgb, plutovg_canvas_fill_preserve and plutovg_canvas_stroke, with plutovg_canvas_save and plutovg_canvas_restore managing the transform stack.

What licence is PlutoVG released under?

The MIT Licence, with the licence file in the repository. The current release is v1.3.3 from 2026-05-18 and the last push to the repository was on 2026-07-16.

Official sources

  1. Issues
  2. License: MIT
  3. README
  4. Releases
  5. sammycage/plutovg on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/sammycage-plutovg.svg)](https://hysenlabs.com/projects/sammycage-plutovg)

Was this useful?