# I figured out how to render SVG effects in JUCE

**URL:** <https://forum.juce.com/t/i-figured-out-how-to-render-svg-effects-in-juce/52953>\
**Category:** General JUCE discussion\
**Created:** [September 9, 2022, 6:43pm UTC](https://forum.juce.com/t/i-figured-out-how-to-render-svg-effects-in-juce/52953 "2022-09-09T18:43:06Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![intalentive](https://avatars.discourse-cdn.com/v4/letter/i/aca169/32.png) [@intalentive](https://forum.juce.com/u/intalentive)\
**Post date:** [September 9, 2022, 6:43pm UTC](https://forum.juce.com/t/i-figured-out-how-to-render-svg-effects-in-juce/52953/1 "2022-09-09T18:43:06Z")

</div>

This Rust library parses AND renders most of the SVG spec:

> **[GitHub - RazrFalcon/resvg: An SVG rendering library.](https://github.com/RazrFalcon/resvg)**
>
> An SVG rendering library. Contribute to RazrFalcon/resvg development by creating an account on GitHub.

What is missing is animations. But all the features for static images are there. The author helpfully included code that compiles Rust to both static and dynamic libraries along with a C header file. Adapting the `example.c` code from the `c-api/examples/cairo/` folder, I was able to render SVG directly to `juce::Image` like so:

```auto
#include <resvg.h>

// load SVG into internal tree representation
resvg_render_tree *tree;
resvg_init_log();    
resvg_options *opt = resvg_options_create();
resvg_options_load_system_fonts(opt);
int err = resvg_parse_tree_from_file("/path/to/file.svg", opt, &tree);
resvg_options_destroy(opt);
if (err != RESVG_OK)
{
    printf("Error id: %i\n", err);
    abort();
}

// get dimensions, assume painting at origin
resvg_size size = resvg_get_image_size(tree);
int width = (int)size.width;
int height = (int)size.height;
int x = 0;
int y = 0;

// setup image to render to
juce::Image img (juce::Image::PixelFormat::ARGB, width, height, true);
juce::Image::BitmapData bmp (img, x, y, width, height);
    
// fit SVG parse tree to original, width, height, or zoom factor
resvg_fit_to fit_to = { RESVG_FIT_TO_TYPE_ORIGINAL, 0 };

// render directly into image data (no cairo surface necessary)
resvg_render(tree, fit_to, resvg_transform_identity(), width, height, (char*)bmp.data);
resvg_tree_destroy(tree);
    
// RGBA -> BGRA
for (int i = 0; i < width * height * 4; i += 4)
{
    unsigned char r = bmp.data[i + 0];
    bmp.data[i + 0] = bmp.data[i + 2];
    bmp.data[i + 2] = r;
}
  
g.drawImageAt(img, x, y);

```

(Of course, in your component class you’ll probably want to keep the parse tree as a member variable and free it in the destructor.)

The downside to this approach is an extra ~9 MB to final executable size. And since it is in C there is a tiny bit of memory management to handle. Also, it isn’t “JUCE native” in the sense of converting to paths and fills.

But overall this is the simplest, easiest solution I have found for getting SVG effects into my JUCE project, and to link everything up it only took an extra 3 lines in CMake. I hope this is helpful! Took a bit of trial and error to figure this out, and I didn’t find any satisfactory solutions in the forums here or in the Audio Programmer Discord. The next step may be to wrap this library into a more user-friendly C++ API.

Here is an example render from [SVG filter effects - Wikipedia](https://en.wikipedia.org/wiki/SVG_filter_effects#/media/File:Catan_Universe_fixed_setup.svg:)

 ![image](https://us1.discourse-cdn.com/flex026/uploads/juce/original/2X/7/7defbb7772eb1fac6055aa2bfb2739487a307209.jpeg)

Textures: feTurbulence, feDiffuseLighting, feDistantLight, feComposite and feBlend  
Shadows: feGaussianBlur, feOffset, feColorMatrix and feBlend

---

<div class="post-metadata">

**Author:** ![ImJimmi](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/imjimmi/32/10843_2.png) [@ImJimmi](https://forum.juce.com/u/ImJimmi)\
**Post date:** [September 9, 2022, 7:18pm UTC](https://forum.juce.com/t/i-figured-out-how-to-render-svg-effects-in-juce/52953/2 "2022-09-09T19:18:48Z")

</div>

This is really cool - I’ll definitely be giving this a go!

One thing that I’m skeptical of is the performance… drawing a `juce::Image` is almost always more expensive than rendering an SVG of the same size. Using this approach, not only do you have a potentially more expensive SVG rendering since it supports the more advanced SVG feautres, but you then have the expensive operation of drawing the resultant image to the graphics context. I suppose for static graphics that would be totally fine, but for dynamic content wth animations I wonder what sort of framerate you’d get.

Is that something you’ve looked at? Have you benchmarked this approach and/or measured framerate while repainting repeatedly?

---

<div class="post-metadata">

**Author:** ![Toddler-Boy](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/toddler-boy/32/2007_2.png) [@Toddler-Boy](https://forum.juce.com/u/Toddler-Boy)\
**Post date:** [September 9, 2022, 7:28pm UTC](https://forum.juce.com/t/i-figured-out-how-to-render-svg-effects-in-juce/52953/3 "2022-09-09T19:28:36Z")

</div>

> [@ImJimmi](#):
>
> drawing a `juce::Image` is almost always more expensive than rendering an SVG of the same size

Maybe if the SVG is a single path with a solid color. If you draw anything more complex and with gradients, the juce::Image will draw faster.

---

<div class="post-metadata">

**Author:** ![intalentive](https://avatars.discourse-cdn.com/v4/letter/i/aca169/32.png) [@intalentive](https://forum.juce.com/u/intalentive)\
**Post date:** [September 9, 2022, 7:28pm UTC](https://forum.juce.com/t/i-figured-out-how-to-render-svg-effects-in-juce/52953/4 "2022-09-09T19:28:38Z")

</div>

The resvg library doesn’t handle any animations at all, so that’s a moot point.

I haven’t benchmarked performance, but for my particular application – drawing effects on 20x20 px elements – I have assumed that any performance hit will be negligible.

Really what I am comparing this against is resizing and applying effects to PNGs, rather than against a full-fledged replacement for JUCE’s current SVG capability. That might require a dedicated backend like Cairo.

---

<div class="post-metadata">

**Author:** ![ImJimmi](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/imjimmi/32/10843_2.png) [@ImJimmi](https://forum.juce.com/u/ImJimmi)\
**Post date:** [September 9, 2022, 7:34pm UTC](https://forum.juce.com/t/i-figured-out-how-to-render-svg-effects-in-juce/52953/5 "2022-09-09T19:34:36Z")

</div>

I’ve always found drawing a `juce::Drawable` constructed from an SVG element to render much faster than an Image - but maybe there’s other platforms and things I’ve not considered.

---

<div class="post-metadata">

**Author:** ![ImJimmi](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/imjimmi/32/10843_2.png) [@ImJimmi](https://forum.juce.com/u/ImJimmi)\
**Post date:** [September 9, 2022, 7:37pm UTC](https://forum.juce.com/t/i-figured-out-how-to-render-svg-effects-in-juce/52953/6 "2022-09-09T19:37:29Z")

</div>

> [@intalentive](#):
>
> The resvg library doesn’t handle any animations at all, so that’s a moot point.

Ahh sorry, I misread your post!

> [@intalentive](#):
>
> I haven’t benchmarked performance, but for my particular application – drawing effects on 20x20 px elements – I have assumed that any performance hit will be negligible.

Yeah for an image that small I wouldn’t expect to run into any massive issues with performance!

> [@intalentive](#):
>
> Really what I am comparing this against is resizing and applying effects to PNGs, rather than against a full-fledged replacement for JUCE’s current SVG capability.

I see, yeah I can see this being a better solution for that. I was hoping this might serve as a good replacement for JUCE’s SVG rendering and could be a good solution for rendering shadows, blurs, etc. on components - especially animated ones that move and change size.
