Shadows for svg buttons

Hi, as juce doesn’t seem to render svg shadows (!) what’s the best practice for handling this?

Do people just use bitmaps or add drop shadows in the paint() method after all controls have been placed on the screen? Is there a better way to handle this?

Thanks

Shadows are a real pain-point for me, I’ve tried numerous times to find a neat solution but nothing ever sticks.

Currently, we have a ShadowComponent that can be attached to another component. They can be inner or outer shadows so they either place themselves on top or behind the component they’re attached to. For outer shadows, they need to be made a little bigger to show the shadow outside the bounds of the component being shadowed - this leads to all sorts of edge cases, like when the component being shadowed is against the edge of its parent’s bounds, so then the shadow gets clipped (unless you put the shadow even higher in the parent hierarchy but then it’ll likely get drawn behind the wrong things).

As for drawing them - the shadow component just uses juce::DropShadowEffect in its paint() method - since the things with shadows don’t change their size, the shadow only ever gets drawn once (as long as you call setBufferedToImage(true) on them). If they could be resized, then yeah drawing to an image and just scaling that image to fit the correct size is possibly the way to go - although then your blur radius won’t be consistent.

You can optimise the image method using 9-slice scaling. If the component being shadowed doesn’t have any transparency - you can just use 8 images for the corners and edges, which saves you drawing a large chunk of pixels.

1 Like

thanks - i’ve just played around with the shadowcomponent and it seems very “square” and unnatural. sounds like there’s going to be a lot of tweaking ahead from your description also.

We give the shadow component a path (to represent the outline of the component being drawn, as they usually have rounded corners), and a juce::DropShadow. The size of the shadow component is the size of the thing being shadowed, expanded by the blur radius, then offset the position of the shadow component with the offset from the drop shadow. When you draw the shadow to the shadow component, use an offset of (0, 0) as you’ve already account for that.

It can be a bit fiddly to get all the scaling, relative positions, etc. done right.

ah, interesting - i’ll give that a go - thanks for the tips

1 Like

How do you convert the SVG to a JUCE path? thx

Drawable::parseSVGPath() should do the trick.

IIRC that expects a <path> element from within an SVG, not the entire SVG document itself. I may be wrong but I recall coming across something along those lines before.

Looks like you’re right, my mistake!

I thought I had used that in the past, but it looks like I ended up creating a Drawable object from the SVG data and calling getOutlineAsPath() to get its Path. Might give that a try if you haven’t already found a solution @leehu

thanks for all the info. i’ve got some basic shadows up and running now - doesn’t quite look as good as the shadows in the svg, but I guess it’ll do.

Any pointers on drawing internal shadows to give the highlight effect here:

image

With some exports we got from Adobe, the shadow was png embedded and didn’t properly draw.
extracting the embedded png worked ok here.

Also, drawing a shadow using juce effect might have a performance hit. so it’s worth pre-rendering it.

Afaik shadows aren’t a builtin feature of SVG, and may be implemented in several different ways, some of which JUCE might render correctly. So these sort of reports would probably work best with an example .svg file.