Help adapting SVGs

My app has lots of cells that look something like this:

image

The default shape is a rounded rectangle, but I want the user to be able to load their own shapes using SVGs (just simple things like stars or arrows). The user will enter text and the Drawable class interprets it as SVG. I don’t know much about SVGs, and I’m kind of hoping that I don’t need to learn too much in order to get it working.

I have two main questions at this stage. Firstly the cell has a border which draws under some circumstances but not others (it’s visible in the picture above, but if the cell weren’t selected then it wouldn’t be). I’m hoping though that the user doesn’t have to worry about this when they enter their SVG–they can just enter the raw outline of the shape and my C++ code will derive the correct outline. Is this possible?

My second question is about scaling. I want the user to define the shape but not the size of the cell. There are other parts of my code which already scale the cell, and I’d like to keep those intact. I can think of two possible ways of doing this: either I can scale the SVGs after the user enters them to the correct size, or I can test them to make sure that they’re the right size (and reject them if not). Are either of these options possible?

I’m hoping that both of these problems are solvable using only JUCE code, but I’m willing to think about third party options also if necessary.

Hi there!

The first problem sounds like it has to do with defining the correct colour for when the button is selected. Look in the CoulorIds. It should be easy to fix.

For the second, you could turn the SVG into a Path and then “normalise” it. This way the users can scale their SVG however they want. For example:

const juce::Path pathFromSVG (const juce::String& svg)
{
    auto path = juce::Drawable::parseSVGPath (svg);
    path.scaleToFit (0, 0, 1.0f, 1.0f, true);
    return path;
}

For simple stuff (for example if you use something like this online tool: SvgPathEditor) this works great.

Hope this helps!

1 Like

Thanks @aamf, path.scaleToFit() looks like exactly what I’m after.

The first problem doesn’t have to do with colours though, perhaps I explained in badly. It’s just to do with the defining the shape and its border. Right now I’m doing something like this:

void paint(Graphics& g)
{
    Path fill_path = getFillPath();
    Path border_path = getBorderPath();

    g.fillPath(fill_path);

    if(cellRequiresBorder())
        g.strokePath(border_path);
}

As you can see, I’m using two separate paths, one for drawing the border and one for the fill. (It’s been a while since I’ve visited this section of the code, but I think that I tried to do it with one path and found that the spacing was off or something). But what I’d like to do would be something like this:

void paint(Graphics& g)
{
    auto path = juce::Drawable::parseSVGPath (svg); // obviously I won't really do this in the paint() method

    path.scaleToFit();
    g.fillPath(path);
    
    if(cellRequiresBorder())
        g.strokePath(path);
}

Does this seem like it should work?

Edit: I should mention that I’m doing some pretty heavy Affine transformation on these cells…

Yes, that should work, it’s pretty much what I do myself.

You could also always stroke the path; just use the same color as the cell when you don’t want it to look stroked.