femtovg: a Rust 2D vector renderer built on NanoVG's design
Antialiased 2D vector drawing library written in Rust
At a glance
- What is it?
- femtovg is an antialiased 2D vector drawing library written in Rust, ported from the C NanoVG project and now carrying an OpenGL ES and a WGPU path. The feature set covers gradients, filters, layers, masks and text shaping, while custom shaders and 3D transforms remain open items.
- Who is it for?
- Adopt femtovg if you need a self contained 2D vector rasteriser in Rust and can accept a fixed rendering pipeline with no custom shaders and no 3D transforms. Do not pick it when you need programmable shaders or want to stay inside the original NanoVG C codebase, since femtovg is a port of that project rather than a drop-in replacement.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly Rust, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A 2D vector renderer for Rust programs that draw on the GPU
femtovg is a library for drawing antialiased 2D vector graphics from Rust. It targets a specific problem: you want a path, fill, gradient or glyph rendered with smooth edges, and you want to own the pipeline rather than embed a browser, a widget toolkit or a general graphics framework to get there.
The scope is 2D only, and the project is explicit about the boundary. Custom shaders and 3D transforms appear in the not supported list. Everything else a 2D renderer normally needs is checked off: Bezier path filling and stroking, solid colour and image pattern fills, box, linear, radial and conic gradients with multi-stop colours and gradient transforms, stroke width and miter limit, butt, round and square caps, miter, round and bevel joins, stroke dashing with dash offset, even-odd and non-zero fill rules, rectangle scissoring with rounded corners, arbitrary path clipping, composition modes, image filters, layers, layer masks, global alpha, text filling and stroking, text shaping, text alignment, nearest font matching and path hit testing.
For a reader deciding whether to adopt it, the interesting part is not the checklist. It is where the rendering happens and how much of the pipeline is fixed, because those determine whether a given product idea is reachable with this library.
A port of NanoVG, with several parts rewritten in Rust style
The project's lineage is stated plainly at the top of its documentation: it is ported from the C project at github.com/memononen/nanovg. The description of the porting effort is equally plain. Most of the implementation is the same as the original C code, with some bug fixes, some features added and several parts made more Rust-y.
That framing is useful for anyone weighing alternatives, because it tells you the geometry and rasterisation behaviour come from a design that already existed, and the Rust work concentrated on the parts that Rust improves rather than on a fresh architecture. The optional dependencies in Cargo.toml show where that work went: rustybuzz for text shaping, unicode-bidi and unicode-segmentation for bidirectional and segment handling, ttf-parser and swash for font parsing, and slotmap and lru for the resource bookkeeping that Rust's type system can express directly.
The consequence is a library that behaves like NanoVG in most respects, so anyone who knows the C original can predict most of the API shape, and a library that is not a C library in a different syntax. The added features, filters, layers, masks and conic gradients among them, are presented as additions on top of the original C code.
Two backends in the manifest, one backend in the prose
Here the documentation contradicts itself, and the dependency file is the more current source.
The feature list names two rendering backends, an OpenGl ES2 backend and a WGPU backend, and Cargo.toml carries matching optional dependencies:
glow = { version = "0.18.0", default-features = false }
wgpu = { version = "30.0.0", optional = true, default-features = false, features = ["wgsl"] }
glutin = { version = "0.32", optional = true, default-features = false }Yet the introductory text says rendering is done via one OpenGl ES 3.0+ backend, which does not match either the feature list or the presence of glutin and wgpu in the manifest. If you are choosing a backend, read Cargo.toml and the feature flags in the crate documentation rather than trusting the summary paragraph.
The target specific dependencies sharpen the picture. glutin is listed only for targets that are not wasm32, and a separate table matches an alias in build.rs for wasm32 unknown targets, pulling in web_sys with WebGl2RenderingContext and WebGlContextAttributes among its features, alongside wasm-bindgen:
[target.'cfg(all(target_arch = "wasm32", target_os = "unknown"))'.dependencies]
web_sys = { version = "0.3", package = "web-sys", features = [
"WebGlContextAttributes",
"HtmlImageElement",
"CanvasRenderingContext2d",
"WebGl2RenderingContext",
] }
wasm-bindgen = "0.2"So the wasm target pulls in WebGL 2 canvas bindings alongside the wasm glue.
Fixed pipeline means filters and layers, but no custom shaders
Because custom shaders are unsupported, the filter and layer features work through the library's own machinery rather than through your own graphics code.
Image filters include gaussian blur, colour matrices matching the CSS filter functions, Perlin turbulence as the SVG feTurbulence equivalent, and the sRGB transfer curve, chained in a single call. Layers offer group capture with declared opacity and layer filters, corresponding to the Canvas 2D beginLayer and endLayer calls and to SVG group effects. Layer masks come in luminance and alpha variants, matching the SVG mask and mask-type concepts. These are the pieces of SVG rendering that a typical 2D library leaves out, and femtovg has them.
The trade is that you get a rich, opinionated pipeline and no way to add your own stage to it. If your product needs a custom compute pass, a bespoke blend, or a shading model, the fixed pipeline is the boundary, and there is no extension point in the feature list for it.
Text is the other area with real depth. The library does filling and stroking, shaping, alignment on both axes with left, center and right plus top, middle, alphabetic and bottom, nearest font matching, and colour fonts. The optional ttf-parser and swash dependencies are what make the font side possible, and rustybuzz handles the shaping.
The examples are the fastest way to see what it does
The documentation drives you to the examples, and the repository ships a substantial set: demo, breakout, svg, text, gradients, many_rects, paint_filter, paint_image, shader, font_variations, plus helpers and assets, with an examples/README.md and an index.html alongside them.
Each of the four highlighted examples runs with cargo:
cargo run --example democargo run --example breakoutcargo run --example svgcargo run --example textThe demo covers the general drawing path, breakout shows a small interactive scene, svg shows the SVG-oriented features, and text isolates the font and shaping work. The screenshot the documentation pairs with each one is the ground truth for what to expect on screen, and the example set doubles as a working reference for the API because the source sits in the repository.
There is one name in that list worth a second look. An example file called shader.rs sits among the examples even though custom shaders are listed as not supported, so the file name and the feature list do not line up on their face. Read that example before assuming it demonstrates a shader API the feature list does not offer.
Minimum Rust version disagrees with the badge
The documentation badge advertises rust: 1.70 as the minimum supported Rust version, and the book link sits next to it. The manifest disagrees:
[package]
name = "femtovg"
version = "0.27.0"
edition = "2021"
rust-version = "1.88"The manifest is the authoritative value for the build, so 1.88 is what cargo enforces, and the badge is stale. That matters for CI images and for teams pinned to a toolchain, since a 1.70 build environment will fail on the manifest rather than on anything in the code.
The rest of the manifest is plain enough to read as documentation. The crate is described as an antialiased 2D vector drawing library with the keywords graphics, canvas, vector, drawing and gpu, and the licence field reads MIT OR Apache-2.0. The release profile keeps debug info in release builds, which is worth knowing if you plan to symbolicate a profile from a shipped binary.
The version number in the manifest, 0.27.0, is at the zero release line, so the public API is still free to move. The changelog file in the repository root is where to look for what moved.
Dual licensing, and licences inside the example assets
femtovg is offered under a choice of two licences, Apache License 2.0 and the MIT licence, at your option, with LICENSE-APACHE and LICENSE-MIT at the repository root and the same files referenced under docs. In plain terms, that is a permissive pair of licences with an explicit choice, and it is the kind of licensing that does not complicate commercial use or redistribution.
The assets are a separate matter and are worth reading carefully. The documentation lists the fonts used in the examples: Roboto under the Apache licence, Entypo under CC BY-SA 4.0, and Amiri under the SIL Open Font License 1.1. The third one is fine to embed. The second is the one to look at, because CC BY-SA is a share-alike licence with attribution conditions, and a font file that ships in a binary distribution is exactly the situation where that matters.
Those licences cover the example assets only. They do not reach the library, which is dual licensed Apache or MIT, and they do not reach fonts you supply yourself at runtime, which are governed by whatever licence you obtained them under.
The repository is not archived. The last push was on 2026-10-20, and the recent release line moved 0.25.1 on 2026-05-29, 0.26.0 on 2026-07-20 and 0.27.0 on 2026-08-31. That is three releases across about three months, and the 0.x version number still means the API can change between them.
Editorial conclusion
Adopt femtovg if you need a self contained 2D vector rasteriser in Rust and can accept a fixed rendering pipeline with no custom shaders and no 3D transforms. Do not pick it when you need programmable shaders or want to stay inside the original NanoVG C codebase, since femtovg is a port of that project rather than a drop-in replacement. Verify first that the OpenGL ES and WGPU backends in the dependency list match the graphics stack you target, and check Cargo.toml for rust-version = "1.88" against the toolchain in your build environment.
Frequently asked questions
What is femtovg used for and what does it not support?
femtovg is an antialiased 2D vector drawing library written in Rust for rendering paths, gradients, text, filters, layers and masks on the GPU. Custom shaders and 3D transforms are explicitly listed as not supported.
Which Rust version do I need to build femtovg?
Cargo.toml sets rust-version = "1.88" and the crate is edition 2021, so that is the version cargo enforces even though the documentation badge still advertises rust 1.70. The badge is out of date with the manifest.
How do I run the femtovg examples?
The examples are run with cargo, for example cargo run --example demo, with breakout, svg and text as the other four highlighted examples. The examples directory also holds gradients, many_rects, paint_filter, paint_image, shader and font_variations.
Can femtovg render text with shaping and colour fonts?
Yes. The feature list covers text filling and stroking, text shaping, alignment on both axes, nearest font matching and colour fonts, with optional rustybuzz, ttf-parser, swash, unicode-bidi and unicode-segmentation dependencies behind the font work.
What licence applies to femtovg and to its example fonts?
The library is offered under the Apache License 2.0 or the MIT licence at your option, with LICENSE-APACHE and LICENSE-MIT in the repository. The example fonts carry their own terms: Roboto under Apache, Entypo under CC BY-SA 4.0, and Amiri under the SIL Open Font License 1.1.
Official sources
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.
[](https://hysenlabs.com/projects/femtovg-femtovg)Was this useful?