top of page

Build & Installation

You can download the ThorVG tarball via the Releases link.  The latest version is recommended. 

ThorVG supports meson build system. Install the meson and ninja if you don't have them already.

Run meson to configure ThorVG in the thorvg root folder.

meson . builddir

Run ninja to build & install ThorVG:

ninja -C builddir install

Regardless of the installation, all build results (symbols, executable) are generated in the builddir folder in thorvg. Some results such as examples won't be installed, you can check "More examples" section to see how to change it.

Note that some systems might include ThorVG package as a default component. In that case, you can skip this manual installation.

Using with Visual Studio

If you want to create Visual Studio project files, use the command --backend=vs. The resulting solution file (thorvg.sln) will be located in the build folder.

meson build --backend=vs

Using vcpkg

You can download and install pre-packaged ThorVG using the vcpkg package manager.

Clone the vcpkg repo. Make sure you are in the directory you want the tool installed to before doing this.

Run the bootstrap script to build the vcpkg.


Install the ThorVG package. 

./vcpkg install thorvg

Basic Programming

ThorVG supports C++ Programming Interfaces. The following is a quick-start to show you how to use the essential APIs. As the prerequisite, include the ThorVG header file in your source code.

#include <thorvg.h>


In the first step, initialize the ThorVG engine. This prepares and runs the engine internal steps.

//initialize sw engine

tvg::Initializer::init(tvg::CanvasEngine::Sw, 0);

The second parameter of the Initializer::init() requires the ThorVG designated threads number. To use full capacity of the system, you can pass the number of threads to run ThorVG tasks. It will spawn the threads and run Task-Scheduler to progress multiple jobs asynchronously. If you don't know the exact number, you can use std::thread::hardware_concurrency() instead.

ThorVG renders vector scenes to the given canvas buffer. The following shows you an example how to prepare an empty canvas for drawing: 

//canvas target buffer

static uint32_t buffer[WIDTH * HEIGHT];

//generate a canvas

auto canvas = tvg::SwCanvas::gen();

//setup canvas target

canvas->target(buffer, WIDTH, WIDTH, HEIGHT, tvg::SwCanvas::ARGB8888);

If you have your own canvas buffer memory, you can pass its pointer to the canvas. SwCanvas::target() requires five parameters: buffer memory, buffer stride size, canvas width, height and Colorspace. The last parameter determines the format of the pixel color channels used during drawing scene on the canvas buffer.


Once a canvas is ready, you can create shapes by pushing them to the canvas.

//generate a shape

auto rect = tvg::Shape::gen();
//append a rounded rectangle to the shape (x, y, w, h, rx, ry)

rect->appendRect(50, 50, 200, 200, 20, 20);

//set shape color (r, g, b, a)

rect->fill(100, 100, 100, 255);         

//push the shape into the canvas

In the example above, a shape is generated and then a rounded rectangle is appended to it. ThorVG provides predefined shape types such as rectangle, circle and arc for the user's convenience. You can append any custom shape by using Paths. ThorVG allows you to append multiple forms into a shape, to compose a more complex one. A complex shape shares its properties, such as color, stroke, fill, etc., among the appended forms.

After a rounded rectangle is appended, its color is set and then the shape is pushed to the canvas.

This shape from the example looks as follows:



Besides predefined shape types, you can compose arbitrary shape types using a path concept. A path is a list of commands that are commonly used in traditional 2D vector drawing. Below you can see an example of how to define your own forms.

//generate a shape

auto path = tvg::Shape::gen();        
//set sequential path coordinates

path->moveTo(199, 34);
path->lineTo(253, 143);
path->lineTo(374, 160);
path->lineTo(287, 244);
path->lineTo(307, 365);
path->lineTo(199, 309);
path->lineTo(97, 365);
path->lineTo(112, 245);
path->lineTo(26, 161);
path->lineTo(146, 143);

//complete the path

//set shape color (r, g, b, a)

path->fill(150, 150, 255, 255);
//push the shape into the canvas

By using the Path, lines and Bezier curves can be drawn. Additionally, you can set preset list using Shape:appendPath() for optimal data delivery.

The output of the example is as follows:



Besides the solid color, ThorVG supports two kinds of gradient fill: linear and radial. Fundamentally, choosing the gradient fill effect is up to the user. However, it often adds some aesthetics to the shapes. The example below shows how to create a circle with a shading effect.

//generate a shape

auto circle = tvg::Shape::gen();
//append a circle to the shape (cx, cy, rx, ry)

circle->appendCircle(400, 400, 100, 100);

//generate a radial gradient
auto fill = tvg::RadialGradient::gen();
//set the radial gradient geometry info (cx, cy, radius)

fill->radial(400, 400, 150);

//gradient colors
tvg::Fill::ColorStop colorStops[2];
//1st color values (offset, r, g, b, a)

colorStops[0] = {0.0, 255, 255, 255, 255};

//2nd color values (offset, r, g, b, a)
colorStops[1] = {1.0, 0, 0, 0, 255};

//set the gradient colors info
fill->colorStops(colorStops, 2);

//set the shape fill

//push the shape into the canvas



Stroking enables you to draw the outline of shapes as well lines. You can simply add stroke properties to a shape if needed. Stroke supports both a solid color and a gradient fill and also 4 major properties - width, cap, join and dash pattern.

//generate a shape
auto rect = tvg::Shape::gen();
//append a round rectangle to the shape (x, y, w, h, rx, ry)
rect->appendRect(50, 50, 200, 200, 20, 20);
//set shape color (r, g, b, a)
rect->fill(100, 100, 100, 255);

//stroke width
//stroke color

rect->stroke(50, 50, 50, 255);

//stroke join style

//stroke cap style

//stroke dash pattern (line, gap)
float pattern[2] = {7, 10};

//set the stroke pattern
rect->stroke(pattern, 2);   

//push the shape into the canvas


Scene & Transformation

ThorVG provides an interface to build Paint groups by composing multiple Paints. This is useful when you consider a scene-graph structure and manipulate a scene as a control unit. The code below shows how to use the ThorVG Scene and transform it.

//generate a Scene
auto scene = tvg::Scene::gen();

//generate a round rectangle
auto rect = tvg::Shape::gen();
rect->appendRect(-235, -250, 400, 400, 50, 50);
rect->fill(0, 255, 0, 255);

//push the rectangle into the scene

//generate a circle
auto circle = tvg::Shape::gen();
circle->appendCircle(-165, -150, 200, 200);
circle->fill(255, 255, 0, 127);

//push the circle into the scene

//generate an ellipse
auto ellipse = tvg::Shape::gen();
ellipse->appendCircle(265, 250, 150, 100);
ellipse->fill(0, 255, 255, 255);

//push the eliipse into the scene

//transform the scene
scene->translate(350, 350);

//push the scene into the canvas

All kinds of Paint type nodes (Shape, Scene and Picture) can be pushed into the Scene as its children. You can scale this logic and build a complex scene by compositing multiple Scenes. In the example, we create a scene-graph tree and we demonstrate how to transform it using translate(), scale(), rotate() methods. ThorVG also supports the transform() method which expects a transformation matrix.



The Picture is a special component that is designed to draw a scene on the Canvas from image data. ThorVG supports several image formats including vector-based and bitmap-based formats.

//generate a picture (svg)
auto svg = tvg::Picture::gen();
//load a svg file
//push the picture into the canvas

//generate a picture (png)

auto png = tvg::Picture::gen();

//load a png file


//set the desired size

png->size(300, 300);

//set the position

png->translate(150, 150);

//push the picture into the canvas




ThorVG applies composition for visual effects such as blending, masking, filtering, etc. You should be aware though, that a composition may perform an additional render-processing on an off-screen buffer. The excessive usage of a composition won't be helpful if lightweight processing is a priority for you. A hint - sometimes you can avoid a composition by changing the application or the design approach while maintaining the same visual effects.

//generate a picture

auto picture = tvg::Picture::gen();

//generate a circle for masking
auto mask = tvg::Shape::gen();

mask->appendCircle(250, 325, 225, 225);

mask->fill(255, 255, 255, 255);

//set circle alpha mask to the picture
picture->composite(move(mask), tvg::CompositeMethod::AlphaMask);
//push the picture into the canvas


Drawing, the last step

Once you've prepared all the paint nodes by pushing them into the canvas, you can request the drawing task as the last step. Canvas::push() API starts the preprocessing task for the rendering, however it doesn't start the rasterization. Since all the tasks under the hood can be performed asynchronously, you need to call Canvas::sync() at the optimal point of time. Then, finally you will get a completed image in the target buffer.



After getting the frame image, you can flush out all the pushed paint nodes from the canvas with Canvas::clear() call.

More examples

There are plenty of sample code in thorvg/src/examples to help you in understanding the ThorVG APIs.

To execute these examples, you can build them with the following meson build option:

meson . builddir -Dexamples=true

Note that these examples require the EFL dev package for launching. If you're using Linux-based OS, you can easily install this package from your OS distribution server. For Ubuntu, you can install it with this command.

apt-get install libefl-all-dev

Please visit the official EFL page for more information.

bottom of page