SVG workflow

Just wanted to let you know a couple of nice tools I’ve been using while incorporating some SVGs into our code. My workflow has been:

  • Design SVG in Figma
  • Export as SVG (batch export using ctrl shift e)
  • Use bash script & Scour to:
    • optimize the SVGs in a batch
    • convert the filenames to legal cpp variable names
    • add R"svgDELIM(
  • Paste the SVGs + variable names into VS Code
  • Use Inline SVG Preview to make sure I don’t get things mixed up.

Hope that’s useful.

6 Likes

Sounds pretty cool … tell us more about the “convert filenames to legal cpp variable names” and “add R"svgDELIM(” steps - why are they necessary, what do they provide you, etc?

I dream of a day I can just compose the entire interface for an app in SVG, name things properly, and get a fully integrated component that’s just waiting to be wired up …

2 Likes

Thanks! I didn’t know about Scour and made svg-simplify to help with two features lacking in JUCE’s SVG implementation. Do you know if those (css rule aggregation so styles come from a single group and inlining masks into gradients) are supported by Scour?

Sorry @yairadix , I’ve don’t really know but I get the impression Scour doesn’t go that deep into converting elements.

@anon48770766, I declare the SVG strings in code as raw strings so I don’t have to worry about escaping quotes, etc. The ‘svgDELIM’ is the raw string delimiter. See
https://en.cppreference.com/w/cpp/language/string_literal

The ‘convert the filenames to legal cpp variable names’ is because in Figma I use variants which get named things like ‘button,size=mini,state=active,mouse=hover’ and I might want to use ‘button_size_mini_state_active_mouse_hover’ as the variable name. So you could have bash generate the declarations for you.

Hope that makes sense…

2 Likes

Sounds cool, would love to see some sample code of how you’re effectively using SVG …

I just learnt, to further tidy your Figma SVGs, uncheck ‘clip content’ in Figma (if you’re not using it). This can remove unecessary defs + attributes in your SVG.

Source: More control over Figma SVG exports: Levi McGranahan

1 Like

Sure. After exporting from Figma and running my little script, I might have something like this:

auto settingsicon_mouse_over =
R"svgDELIM(
<svg width="24" height="24" fill="none" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">...</svg>
)svgDELIM";

auto settingsicon_mouse_normal =
R"svgDELIM(
<svg width="24" height="24" fill="none" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">...</svg>
)svgDELIM";

auto settingsicon_mouse_down =
R"svgDELIM(
<svg width="24" height="24" fill="none" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">...</svg>
)svgDELIM";

These will go to create a DrawableButton, which will be a member of some containing component.

DrawableButton settingsicon;

Then, in the constructor of the component which contains the DrawableButton:

auto x_settingsicon_mouse_over {XmlDocument::parse (String (settingsicon_mouse_over))};
jassert(x_settingsicon_mouse_over != nullptr);
auto d_settingsicon_mouse_over {Drawable::createFromSVG (*x_settingsicon_mouse_over)};
jassert(d_settingsicon_mouse_over != nullptr);

auto x_settingsicon_mouse_normal {XmlDocument::parse (String (settingsicon_mouse_normal))};
jassert(x_settingsicon_mouse_normal != nullptr);
auto d_settingsicon_mouse_normal {Drawable::createFromSVG (*x_settingsicon_mouse_normal)};
jassert(d_settingsicon_mouse_normal != nullptr);

auto x_settingsicon_mouse_down {XmlDocument::parse (String (settingsicon_mouse_down))};
jassert(x_settingsicon_mouse_down != nullptr);
auto d_settingsicon_mouse_down {Drawable::createFromSVG (*x_settingsicon_mouse_down)};
jassert(d_settingsicon_mouse_down != nullptr);

settingsicon.setImages(x_settingsicon_mouse_normal.get(), x_settingsicon_mouse_over.get(), x_settingsicon_mouse_down.get());
settingsicon.setButtonText("Settings");
settingsicon.setClickingTogglesState(false);
settingsicon.setEdgeIndent(0);
_settingsMenuButton.onClick = [this]() { menuButtonClicked(); };

addAndMakeVisible(&settingsicon);

Add to resized() of the containing component:

settingsicon.setBounds(x, y, w, h);

I believe this is the most up-to-date way to do this with JUCE…

1 Like

Ah yes indeed, this looks like a smooth way to do it - especially given that, to address perhaps a bit of churn that is generated by tweaking/UI, doing builds etc., the code for the constructor could probably be being generated by your script and included in a header, or maybe I misunderstood that it is already?

Just the SVG definitions are being generated at the moment, the rest is in a function for reuse with other components.

To extend the code generation, a big time saver would be to generate code for resized() that arranges components based on Figma’s auto layout…