Hi,
I'm using the UltraChart component from NetAdvantage 2009.2 and have come across an issue with the dimensions used when rendering a chart to SVG format.
A portion of our application makes use of a custom reporting library, which requires that images are sent to it in SVG format. To satisfy this requirement, I have written a WCF service which serves as a wrapper to the UltraChart component. It accepts 'chart data' as input and produces an SVG (Stream) as output.
However if I specify that the chart must be of a specific size (let's say 800 x 600), the resulting SVG output contains the correct sizing in the header (ie; viewBox="0 0 800 600"), but the remainder of the file contains sizing based on the dimensions of 400 x 300 (ie; width="399" height="299"). This issue occurs no matter what dimensions I specify (ie; the output always uses 400x300).
The only workaround that I have found for this issue, is to force the UltraChart component to render to an 'Image' first, then perform the rendering to SVG.
To reproduce this issue;
1. Create a new Windows Application (I'm using C# ...)
2. Add references to "System.Web", "Infragistics35.WebUI.Shared.v9.2" and "Infragistics35.WebUI.UltraWebChart.v9.2"
3. Copy the following code into the 'form load' of Form1;
Infragistics.WebUI.UltraWebChart.UltraChart loChart = new Infragistics.WebUI.UltraWebChart.UltraChart(); loChart.ID = DateTime.Now.ToString(); loChart.Width = 800; loChart.Height = 600; loChart.BackColor = Color.Blue;
//FileStream loFileStreamImage = File.OpenWrite("d:/temp/output.png"); //loChart.SaveTo(loFileStreamImage, Infragistics.UltraChart.Shared.Styles.RenderingType.Image); //loFileStreamImage.Flush(); //loFileStreamImage.Close();
FileStream loFileStreamSVG = File.OpenWrite("d:/temp/output.svg"); loChart.SaveTo(loFileStreamSVG, Infragistics.UltraChart.Shared.Styles.RenderingType.Svg); loFileStreamSVG.Flush(); loFileStreamSVG.Close();
Run the code 'as is' first (assuming you have a d:/temp folder!) to see the incorrect dimensions in the resulting SVG.
Then uncomment the code which first produces an Image rendering and allow the SVG to be rendered also. The resulting SVG this time contains the correct dimensions.
Questions:
1. Is there something that I need to set or invoke with the UltraChart component to avoid this issue?
2. Is this a bug within the Infragistics code ... or is there something else on my system that requires attention?
I would prefer not having to render to an Image first, each and every time that I need to render to SVG!
Any assistance you can provide in this matter would be greatly appreciated!
Thanks,
Jason.
Seems like a bug to me. From a cursory look, it seems like the SVG rendering isnt first setting the bounds of the chart rendering to the bounds of the component, while the image rendering does. Also if the chart were actually displayed on screen this would be taken care of. I'll confirm I can replicate and then enter this as a bug and get back to you with a bug number, in the meantime, your workaround seems sufficient to make sure the chart has set its rendering bounds before rendering to SVG.
After looking through your code, we can confirm at our end that setting the bounds by calling the method
this.chartCore.SetSize(imageSize.Width, imageSize.Height);
before calling
this.chartCore.DrawChart();
resolves this issue.
We are now using reflection to call the SetSize method before rendering the chart in the SVG format, instead of rendering the entire chart twice.
Object chartCore = null;// Get the private field "chartCore" in the UltraChart class.FieldInfo chartCoreInfo = moChart.GetType().GetField("chartCore", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.DeclaredOnly | BindingFlags.Instance);if (chartCoreInfo != null){ // Get the value of the 'chartCore' object. chartCore = chartCoreInfo.GetValue(moChart);}if (chartCore != null){ // Get the private method "SetSize" on the 'chartCore' object. MethodInfo setSizeMethodInfo = chartCore.GetType().GetMethod("SetSize", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.DeclaredOnly | BindingFlags.Instance, null, new Type[] { typeof(Int32), typeof(Int32) }, null); if (setSizeMethodInfo != null) { // Invoke the 'SetSize' method on the 'chartCore' object. setSizeMethodInfo.Invoke(chartCore, new Object[] { (Int32)moChart.Width.Value, (Int32)moChart.Height.Value }); }}
Ideally we would like to see this done in your code rather than call method reflectively. Is there a bug number that we can track so we can monitor which service release or hotfix this will be fixed in?