Svg to PNG Gradient Issue

Feb 23, 2012 at 12:20 PM
Edited Feb 23, 2012 at 12:34 PM

I'm having an issue with an SVG linear gradient I want to export to PNG/JPG format.

Workflow:

I have an xml/svg file.

 

<svg xmlns="http://www.w3.org/2000/svg" width="280" height="450" version="1.1">
  <g transform="scale(1, 1)">
    <rect id="schuldgraad2008" x="117" y="120" width="16" height="350" fill="url(#schuldgradient)" stroke="none" stroke-width="0"/>
  </g>
  <defs>
    <linearGradient id="schuldgradient" x1="0%" y1="0%" x2="0%" y2="100%">
      <stop offset="24.9494759131441%" style="stop-color:#39AE4A;stop-opacity:1"/>
      <stop offset="27.890811531758%" style="stop-color:#CE2429;stop-opacity:1"/>
    </linearGradient>
  </defs>
</svg>

 

This renders nicely in firefox, chrome, ...

For older IE browsers and other applications I want to export this to PNG and JPG, that's where the SVG Rendering Engine comes in play.

 

Dim newStream As New System.IO.MemoryStream(ASCIIEncoding.Default.GetBytes(newDom.InnerXml))
Dim testSVG As Svg.SvgDocument = Svg.SvgDocument.Open(newStream, Nothing)
Dim tempStream As New System.IO.MemoryStream()
testSVG.Draw().Save(tempStream, System.Drawing.Imaging.ImageFormat.Png)
Dim img As System.Drawing.Image
img = System.Drawing.Image.FromStream(tempStream)
img.Save(tempStream, System.Drawing.Imaging.ImageFormat.Png)
Context.Response.ContentType = "image/png"
Context.Response.BinaryWrite(tempStream.ToArray)

 

This works fine for rectangels, text, lines, polylines, ... Gradients in the definitionlist he does not recognize when importing, a black rectangle gets displayed. I constructed a function to fix this issue. And for testing purposes I cleared the gradient stops and added 3 new ones.

 

Dim myGradient As Svg.SvgLinearGradientServer = CType(mySvg.GetElementById(gradientId), Svg.SvgLinearGradientServer)
myGradient.Children.Clear()
myGradient.Stops.Clear()
myGradient.Stops.Add(New Svg.SvgGradientStop(New Svg.SvgUnit(Svg.SvgUnitType.Percentage, 0), Drawing.Color.DarkCyan))
myGradient.Stops.Add(New Svg.SvgGradientStop(New Svg.SvgUnit(Svg.SvgUnitType.Percentage, 50), Drawing.Color.Aqua))
myGradient.Stops.Add(New Svg.SvgGradientStop(New Svg.SvgUnit(Svg.SvgUnitType.Percentage, 100.0), Drawing.Color.Red))

CType(mySvg.GetElementById(element.Attributes("id").Value), Svg.SvgRectangle).Fill = myGradient


This works fine except for the fact that my gradient is not in the right position.  My gradient starts with DarkCyan at 0px, reaches Aqua at +-120px and reaches RED at +-240px. After It reaches Red the gradient starts all over again in the opposite direction. This leaves me with +-110 pixels that did not receive the right gradient. The Gradient thinks that those 240px is 100%. That's false, 350 is 100%. I uploaded a pic to illustrate my problem

extra information:
-GradientUnits is set at BoundingBox
-SpreadMethod is set at Pad
I played around with all kinds of properties but none solved the problem.

Is this a bug?
Feb 23, 2012 at 3:10 PM
Edited Feb 23, 2012 at 3:35 PM

I played around a bit more and found this strange behaviour

This is the svg rectangle I worked with

<rect id="schuldgraad2008" x="117" y="120" width="16" height="350" fill="url(#schuldgradient)" stroke="none" stroke-width="0"/>

this is a screenshot of what it should look like (svg screenshot)

This is the png conversion

 

And now the strange behaviour, if I change the Y value to 3 this is the PNG output

<rect id="schuldgraad2008" x="117" y="3" width="16" height="350" fill="url(#schuldgradient)" stroke="none" stroke-width="0"/>

 

Keep in mind that the gradient definition never changed, only the Y value in the rectangle. This looks to me as if a variable gets assigned wrong or something like that...

Also if Y equals width in the rectangle, the gradient is correct, but that doesn't make any sense since I dont want my rectangle 350 pixels from the top.

Is it possible to receive the source code and let me debug it and find out what is wrong?