All formats

librsvg

LanguageRust, with a C API (usable from C and C++); also a Rust crate
LicenseLGPL-2.1-or-later
Repositorygitlab.gnome.org/GNOME/librsvg
DocumentationC API reference, development guide
Depends onCairo, Pango, GLib/GIO, libxml2, FreeType, HarfBuzz
Read / writeread (renders to any Cairo surface: PNG, PDF, PS, SVG, screen) / no

librsvg renders static SVG to a Cairo context. It is the SVG engine of the GNOME desktop and gdk-pixbuf, and ImageMagick, libvips, GIMP and Wikipedia’s thumbnailer use it. It supports most of SVG 1.1 and a growing part of SVG 2, CSS stylesheets, filters and text through Pango. It does not run scripts or animations.

The library was ported from C to Rust but keeps its stable C API (rsvg.h). The rsvg-convert command line tool ships with it and converts SVG to PNG, PDF, PS, EPS and SVG.

Installation#

Shell
# Debian / Ubuntu
sudo apt install librsvg2-dev librsvg2-bin   # -bin has rsvg-convert
# Fedora
sudo dnf install librsvg2-devel librsvg2-tools
# macOS
brew install librsvg
# Windows (vcpkg)
vcpkg install librsvg

Compile with pkg-config:

Shell
cc render.c $(pkg-config --cflags --libs librsvg-2.0 cairo) -o render

With CMake:

cmake
find_package(PkgConfig REQUIRED)
pkg_check_modules(RSVG REQUIRED IMPORTED_TARGET librsvg-2.0)
target_link_libraries(myapp PRIVATE PkgConfig::RSVG)

Basic usage: render SVG to PNG#

C
#include <librsvg/rsvg.h>
#include <cairo.h>
#include <math.h>
#include <stdio.h>

int main(void) {
    GError *error = NULL;
    RsvgHandle *handle = rsvg_handle_new_from_file("in.svg", &error);
    if (!handle) {
        fprintf(stderr, "load error: %s\n", error->message);
        g_error_free(error);
        return 1;
    }

    gdouble width = 0, height = 0;
    if (!rsvg_handle_get_intrinsic_size_in_pixels(handle, &width, &height)) {
        width = 512;  // no width/height in the file (only a viewBox)
        height = 512;
    }

    cairo_surface_t *surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
                                                          (int)ceil(width), (int)ceil(height));
    cairo_t *cr = cairo_create(surface);

    RsvgRectangle viewport = {0, 0, width, height};
    if (!rsvg_handle_render_document(handle, cr, &viewport, &error)) {
        fprintf(stderr, "render error: %s\n", error->message);
        g_error_free(error);
    }

    cairo_surface_write_to_png(surface, "out.png");
    cairo_destroy(cr);
    cairo_surface_destroy(surface);
    g_object_unref(handle);
    return 0;
}

rsvg_handle_render_document scales the SVG to fit the viewport, keeping the aspect ratio (preserveAspectRatio).

How to render SVG at a given width#

Pass a larger viewport; the image is scaled, not blurred:

C
gdouble w, h;
rsvg_handle_get_intrinsic_size_in_pixels(handle, &w, &h);
int out_w = 1024;
int out_h = (int)ceil(h * out_w / w);
cairo_surface_t *surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, out_w, out_h);
cairo_t *cr = cairo_create(surface);
RsvgRectangle viewport = {0, 0, out_w, out_h};
rsvg_handle_render_document(handle, cr, &viewport, NULL);

rsvg_handle_set_dpi(handle, 300) changes how physical units (mm, in, pt) convert to pixels; the default is 96.

How to convert SVG to PDF#

Render to a Cairo PDF surface instead of an image surface. Text and shapes stay vectors:

C
#include <cairo-pdf.h>

gdouble w, h;
rsvg_handle_get_intrinsic_size_in_pixels(handle, &w, &h);
// PDF units are points (1/72 inch); SVG pixels are 1/96 inch
cairo_surface_t *pdf = cairo_pdf_surface_create("out.pdf", w * 72.0 / 96.0, h * 72.0 / 96.0);
cairo_t *cr = cairo_create(pdf);
cairo_scale(cr, 72.0 / 96.0, 72.0 / 96.0);
RsvgRectangle viewport = {0, 0, w, h};
rsvg_handle_render_document(handle, cr, &viewport, NULL);
cairo_destroy(cr);
cairo_surface_destroy(pdf);  // writes the file

How to apply a CSS stylesheet#

rsvg_handle_set_stylesheet (librsvg 2.48+) adds user CSS before rendering, for example to recolor an icon:

C
const char *css = "path { fill: #d33 !important; }";
if (!rsvg_handle_set_stylesheet(handle, (const guint8 *)css, strlen(css), &error)) {
    fprintf(stderr, "css error: %s\n", error->message);
    g_clear_error(&error);
}

How to get the bounds of an element and render only it#

C
RsvgRectangle ink, logical;
if (rsvg_handle_get_geometry_for_element(handle, "#logo", &ink, &logical, &error)) {
    printf("ink box: %g,%g %gx%g\n", ink.x, ink.y, ink.width, ink.height);
    cairo_surface_t *s = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
                                                    (int)ceil(ink.width), (int)ceil(ink.height));
    cairo_t *cr = cairo_create(s);
    RsvgRectangle vp = {0, 0, ink.width, ink.height};
    rsvg_handle_render_element(handle, cr, "#logo", &vp, NULL);
    cairo_surface_write_to_png(s, "logo.png");
    cairo_destroy(cr);
    cairo_surface_destroy(s);
}

How to convert from the command line#

Shell
rsvg-convert -w 512 in.svg -o out.png          # PNG, 512 px wide
rsvg-convert -f pdf -o out.pdf in.svg           # vector PDF
rsvg-convert -b white -z 2 in.svg -o out.png    # white background, 2x zoom

Tips#