SVG gradient and shadow not rendered

Hi,

I have an SVG from our graphic designer that has some gradients and filters to create a shadow. JUCE’s Drawable is not rendering all the elements of the SVG correclty.

See the difference here:

Screenshot 2020-11-07 at 12.01.28 Screenshot 2020-11-07 at 12.01.50

(left: JUCE’s Drawable, right: Gapplin preview)

Is there something we can do differently when exporting the SVG file, or when creating/rendering the drawable? We’re using Drawable::createFromSVG() to parse the XML and Drawable::drawWithin to render it.

Here’s the SVG content for reference:

<svg width="29" height="28" viewBox="0 0 29 28" fill="none" xmlns="http://www.w3.org/2000/svg">
<g filter="url(#filter0_d)">
<circle cx="9.61328" cy="9" r="7" fill="white"/>
<circle cx="9.61328" cy="9" r="7" fill="url(#paint0_radial)"/>
<circle cx="9.61328" cy="9" r="6.75" stroke="black" stroke-opacity="0.3" stroke-width="0.5"/>
</g>
<ellipse cx="9.61328" cy="9" rx="5" ry="5" transform="rotate(-180 9.61328 9)" fill="#FFD35B"/>
<ellipse cx="9.61328" cy="9" rx="5" ry="5" transform="rotate(-180 9.61328 9)" fill="url(#paint1_radial)"/>
<g filter="url(#filter1_d)">
<circle cx="9.61328" cy="9" r="7" fill="white"/>
<circle cx="9.61328" cy="9" r="7" fill="url(#paint2_radial)"/>
</g>
<ellipse cx="9.61328" cy="9" rx="5" ry="5" transform="rotate(-180 9.61328 9)" fill="#FFD35B"/>
<ellipse cx="9.61328" cy="9" rx="5" ry="5" transform="rotate(-180 9.61328 9)" fill="url(#paint3_radial)"/>
<defs>
<filter id="filter0_d" x="0.613281" y="0" width="28" height="28" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
<feMorphology radius="1" operator="dilate" in="SourceAlpha" result="effect1_dropShadow"/>
<feOffset dx="5" dy="5"/>
<feGaussianBlur stdDeviation="3"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.3 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/>
</filter>
<filter id="filter1_d" x="2.61328" y="2" width="17" height="17" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
<feOffset dx="2" dy="2"/>
<feGaussianBlur stdDeviation="0.5"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.3 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/>
</filter>
<radialGradient id="paint0_radial" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(7.32482 4.28846) rotate(52.9575) scale(17.877)">
<stop stop-color="#F35533"/>
<stop offset="1" stop-color="#8C321F"/>
</radialGradient>
<radialGradient id="paint1_radial" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(7.97867 5.63462) rotate(52.9575) scale(12.7693)">
<stop stop-color="#F35533"/>
<stop offset="1" stop-color="#AA3B23"/>
</radialGradient>
<radialGradient id="paint2_radial" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(7.32482 4.28846) rotate(52.9575) scale(17.877)">
<stop stop-color="#F35533"/>
<stop offset="1" stop-color="#8C321F"/>
</radialGradient>
<radialGradient id="paint3_radial" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(7.97867 5.63462) rotate(52.9575) scale(12.7693)">
<stop stop-color="#F35533"/>
<stop offset="1" stop-color="#AA3B23"/>
</radialGradient>
</defs>
</svg>

Also interested to see if there is a solution to this. I’ve had the same experience recently, and opted to use png instead, as the components concerned didn’t need to resize. Obviously not ideal if you want it to resize.

The filters feature of SVG probably isn’t supported by JUCE. It will probably take some significant work to support it.

1 Like

The last time I tried Juce’s gradient fills don’t work on Mac OSX. Many things failed on Windows too, which made any graphical changes needing to be tested on all platforms first. So I gave up and used bitmaps instead, that way I could guarantee any artwork would be usable and work great EVERYWHERE :slightly_smiling_face:

I always make PNGs as big as the largest scale needed, and they look great scaled down in Juce.

@DaveH Are you saying that JUCE ColourGradient Class don’t work on OSX or how JUCE transform SVG with gradient don’t work?

This is still kind of work in progress, but I finally decided to switch to a different svg rendering engine (resvg) which works much better and built a JUCE interface around it. Feel free to try it out, raise issues and prs here:

3 Likes

@ losslessgo I think it was actually any circular gradient fill doesn’t work on mac. The bigger picture for me was the uncertainty of the rendering capabilities that forced me to drop it. For example, I tried exporting a simple keyboard shape from Affinity Designer - it failed on Windows, but worked fine in Chrome. Or the SVG would just contain a bitmap version of the graphic, which meant I might as well just render the PNG anyway.
So any art you use on your plug-in will have to be checked over and over again - if you use an artist, they will hate you for the technical difficulties.
For me, all this hassle caused frustration and just slowed down production. I hope others have had more success than I did.

Thanks for explanation, yeah it’s a shame that JUCE doesn’t have an advanced SVG rendering capabilities, if one want to go all vector graphic.

I’ve had it fail on really simple lines and rectangle fills, not advanced stuff at all.

It really depends on when you’ve tried using JUCE’s SVGs, there’s been a lot of fixes with those basic stuff esp. since 2015

I don’t know. Here’s Projucer 6.0.4 trying it’s best to render a wheel SVG just now, with a bright spot at the top:-
You can see the spot is not even in the centre of the dark band, not to mention rotated right by 80 degrees or something…
It looks like this on Windows 10 and Mac OSX in Projucer…
ProjucerVersion

It’s supposed to look like this (alpha background not rendered in Chrome):-
wheelGood

This is why I don’t bother using them any more.

Interesting, could you provide the original .svg file too? (in case someone would want to analyze the bug)

On macOS they do, the scaling in Windows is shite (by design for performance reasons).

I use the AVIR resizer included in Gin on Windows to overcome this limitation.

@ yairadix
Of course, here it is (link below). I wish I had a simpler example, but I removed all the transparencies and gradients from the other SVGs I had lying around to make them work and I don’t have the original files any more.

https://www.quikquak.com/Temp/followWheel.svg

Dave.

As a text file:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" viewBox="0 0 222 222" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:1.41421;">
    <g transform="matrix(1,0,0,1,-145.08,-119.48)">
        <g transform="matrix(1.28,0,0,1.28,0,0)">
            <g transform="matrix(0.973666,0,0,0.973666,5.26685,4.74017)">
                <path d="M200,91C249.12,91 289,130.88 289,180C289,229.12 249.12,269 200,269C150.88,269 111,229.12 111,180C111,130.88 150.88,91 200,91ZM200,103C242.497,103 277,137.503 277,180C277,222.497 242.497,257 200,257C157.503,257 123,222.497 123,180C123,137.503 157.503,103 200,103Z" style="fill:url(#_Radial1);"/>
            </g>
        </g>
    </g>
    <defs>
        <radialGradient id="_Radial1" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(265.588,0,0,265.588,200,97.0339)"><stop offset="0" style="stop-color:white;stop-opacity:1"/><stop offset="0.04" style="stop-color:rgb(177,180,185);stop-opacity:1"/><stop offset="0.08" style="stop-color:rgb(99,104,115);stop-opacity:1"/><stop offset="0.2" style="stop-color:rgb(64,70,83);stop-opacity:1"/><stop offset="0.36" style="stop-color:rgb(38,44,59);stop-opacity:1"/><stop offset="0.53" style="stop-color:rgb(12,19,36);stop-opacity:1"/><stop offset="1" style="stop-color:rgb(0,8,26);stop-opacity:1"/><stop offset="1" style="stop-color:rgb(255,139,0);stop-opacity:0.894118"/><stop offset="1" style="stop-color:rgb(9,9,9);stop-opacity:1"/></radialGradient>
    </defs>
</svg>

From a quick examination, it looks like JUCE doesn’t apply the transform on the radial gradient. If you remove the transforms then you get the same thing in both JUCE’s rendering and in other programs, and it uses the gradient that JUCE uses with the transforms. This can make a useful bug-report.

I suspected a rotation transform, from years of working with 3Ds Max exports. [shudder :slightly_smiling_face:]
It was always the order of things being done, like translation before rotation, or large matrix stacks which gives an incorrect axis of rotation.