Bug: JUCE doesn't support SVG linearGradient

Even though the fill operation checks for a "linearGradient", I don’t see it happening…

Expected:
image

What I found:
image

For more information:

We’ve been using linearGradients in SVGs and they work for us. I suggest to provide the SVG you used for testing so that the JUCE devs could better investigate the bug.

It’s in the supplied Mozilla link! And noted

1 Like

Ok, I found the bug:

<svg viewBox="0 0 10 10" xmlns="http://www.w3.org/2000/svg"
     xmlns:xlink="http://www.w3.org/1999/xlink">
  <defs>
    <linearGradient id="myGradient" gradientTransform="rotate(90)">
      <stop offset="5%"  stop-color="gold" />
      <stop offset="95%" stop-color="red" />
    </linearGradient>
  </defs>

  <!-- using my linear gradient -->
  <circle cx="5" cy="5" r="4" fill="url('#myGradient')" />
</svg>

If you look at the URL tag, url('#myGradient'), the ID is wrapped in single quotes which JUCE ignores, meaning you end up with an ID that looks like myGradient'.


A possible solution is to update parseURL to this:

    static String parseURL (const String& str)
    {
        if (str.startsWithIgnoreCase ("url"))
            return str
                    .fromFirstOccurrenceOf ("(", false, false)
                    .upToLastOccurrenceOf (")", false, false)
                    .unquoted()
                    .substring (1) //To remove the '#'
                    .trim();

        return {};
    }
2 Likes

New linear gradient issue:

<svg width="120" height="240" version="1.1" xmlns="http://www.w3.org/2000/svg">
  <defs>
      <linearGradient id="Gradient1">
        <stop class="stop1" offset="0%"/>
        <stop class="stop2" offset="50%"/>
        <stop class="stop3" offset="100%"/>
      </linearGradient>
      <linearGradient id="Gradient2" x1="0" x2="0" y1="0" y2="1">
        <stop offset="0%" stop-color="red"/>
        <stop offset="50%" stop-color="black" stop-opacity="0"/>
        <stop offset="100%" stop-color="blue"/>
      </linearGradient>
      <style type="text/css"><![CDATA[
        #rect1 { fill: url(#Gradient1); }
        .stop1 { stop-color: red; }
        .stop2 { stop-color: black; stop-opacity: 0; }
        .stop3 { stop-color: blue; }
      ]]></style>
  </defs>

  <rect id="rect1" x="10" y="10" rx="15" ry="15" width="100" height="100"/>
  <rect x="10" y="120" rx="15" ry="15" width="100" height="100" fill="url(#Gradient2)"/>

</svg>

Expected (via Chrome):
image

What I got:
image

Source:

1 Like

As for the second issue, could it be that JUCE and Chrome/SVG-spec just happen to have different definitions for “red” and “blue”?

Naw, it’s that the parser hasn’t a clue about the embedded CSS style in the defs section; it just ignores the style and doesn’t have anything to fallback on so draws black for a fill.

Yeah I see that, I meant the vertical gradient’s issue

I’m guessing you’re strictly talking about lightness between the red and blue blending?

It’s just a guess, but what I think is happening here is that the browsers blend without gamma correction, while JUCE blends with it… What I can say for sure is that JUCE applies a tween instead of a blend function for the gradients.

1 Like