written by Jones (UI)

1. Adding SVGs in Juce using Projucer

We added SVGs to M4S to have icons and images in the tool. SVGs are vector images, which are very light and can be scaled infinately. Vector images are basically the way to go - especially when you work with icons - just like we did in M4S.

So how to add and draw SVGs in JUCE.

In Juce we use the Projucer programm which you can get on the JUCE website. In the Projucer you manage the classes and objects for the build - prebuilding it for any IDE. Before you build it for the IDE you can not only add classes in Projucer - but also resources - anything basically. Whatever file you want to have in the BinaryData of Juce.

In our case we want to add SVGs as resources. Just drag and drop the files or folders into the projucer and add them as resources. Then build it like always to your IDE.

Now we can access the SVG via code.

In this example I read out a Font file, which I added as a resource in projucer.

text_font = std::unique_ptr<Font>(new Font(Typeface::createSystemTypefaceFor(BinaryData::RobotoBold_ttf, BinaryData::RobotoBold_ttfSize)));

Here is a SVG

ScopedPointer<XmlElement> svg_xml_1(XmlDocument::parse(BinaryData::btn_play_svg)); // GET THE SVG AS A XML
ui::helpers::changeColor(svg_xml_1, "#61f0c4"); // RECOLOUR
Drawable svg_drawable_play = Drawable::createFromSVG(*svg_xml_1); // GET THIS AS DRAWABLE

With the drawable object we can basically do whatever we want. Paint it, add to an Drawable Button. In M4S we added theses SVGs to button to display them.

2. Repaint SVGs

We can think of SVGs as documents turned into drawn images. This way we can get the XML document of a SVG and just replace color strings for the SVG. So we make sure the SVGs have a specific default color. In this case “#030104” and then we can replace it.

Simple but effective.

void ui::helpers::changeColor(XmlElement* xml, String color_hex)
{
    forEachXmlChildElement(*xml, xmlnode)
    {
        forEachXmlChildElement(*xmlnode, xmlouterdefs)
        {
            String style = xmlouterdefs->getStringAttribute("style");
            if (style.isNotEmpty())
            {
                style = style.replace("#030104", color_hex, true);
                xmlouterdefs->setAttribute("style", style);
            }

            forEachXmlChildElement(*xmlouterdefs, xmldefs)
            {
                String style = xmldefs->getStringAttribute("style");
                if (style.isNotEmpty())
                {
                    style = style.replace("#030104", color_hex, true);
                    xmldefs->setAttribute("style", style);
                }
            }
        }
    }
}

Draw from SVG.

void ui::helpers::drawFromSVG(Graphics& g, const char* svgbinary, String col_hex, int x, int y, int newWidth, int newHeight, AffineTransform affine)
{
    ScopedPointer<XmlElement> svg(XmlDocument::parse(svgbinary));
    jassert(svg != nullptr);
    ui::helpers::changeColor(svg, col_hex);

    ScopedPointer<Drawable> drawable;

    if (svg != nullptr)
    {
        drawable = Drawable::createFromSVG(*svg);
        drawable->setTransformToFit(Rectangle<float>(x, y, newWidth, newHeight), RectanglePlacement::stretchToFit);
        drawable->draw(g, 1.f, affine);
    }
}