Commit 3838e721 authored by Gertjan van Heertum's avatar Gertjan van Heertum
Browse files

Fixed problems when running in multiple threads. The use of a static matrix...

Fixed problems when running in multiple threads. The use of a static matrix and the use of StringFormat.GenericTypographic seemed to cause problems when used in multi-threading. This is resolved by making the matrix non static and use a copy of the StringFormat.

Also created a new exception for memory overflows. When using multithreading to render a large amount of big images the bitmap creation can fail (due to memory allocation) throwing an error. This is now caught and a specific exception is thrown.
parent 1a5baee0
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
namespace Svg.Exceptions
{
[Serializable]
public class SvgMemoryException : Exception
{
public SvgMemoryException() {}
public SvgMemoryException(string message) : base(message) {}
public SvgMemoryException(string message, Exception inner) : base(message, inner) {}
protected SvgMemoryException(
SerializationInfo info,
StreamingContext context) : base(info, context) {}
}
}
...@@ -107,6 +107,7 @@ ...@@ -107,6 +107,7 @@
<Compile Include="DataTypes\SvgTextPathSpacing.cs" /> <Compile Include="DataTypes\SvgTextPathSpacing.cs" />
<Compile Include="DataTypes\XmlSpaceHandling.cs" /> <Compile Include="DataTypes\XmlSpaceHandling.cs" />
<Compile Include="Document Structure\SvgSymbol.cs" /> <Compile Include="Document Structure\SvgSymbol.cs" />
<Compile Include="Exceptions\SvgMemoryException.cs" />
<Compile Include="ExtensionMethods\UriExtensions.cs" /> <Compile Include="ExtensionMethods\UriExtensions.cs" />
<Compile Include="Filter Effects\ImageBuffer.cs" /> <Compile Include="Filter Effects\ImageBuffer.cs" />
<Compile Include="Painting\GenericBoundable.cs" /> <Compile Include="Painting\GenericBoundable.cs" />
......
...@@ -13,6 +13,7 @@ using ExCSS; ...@@ -13,6 +13,7 @@ using ExCSS;
using Svg.Css; using Svg.Css;
using System.Threading; using System.Threading;
using System.Globalization; using System.Globalization;
using Svg.Exceptions;
namespace Svg namespace Svg
{ {
...@@ -434,17 +435,27 @@ namespace Svg ...@@ -434,17 +435,27 @@ namespace Svg
this.Render(renderer); this.Render(renderer);
} }
/// <summary> /// <summary>
/// Renders the <see cref="SvgDocument"/> and returns the image as a <see cref="Bitmap"/>. /// Renders the <see cref="SvgDocument"/> and returns the image as a <see cref="Bitmap"/>.
/// </summary> /// </summary>
/// <returns>A <see cref="Bitmap"/> containing the rendered document.</returns> /// <returns>A <see cref="Bitmap"/> containing the rendered document.</returns>
public virtual Bitmap Draw() public virtual Bitmap Draw()
{ {
//Trace.TraceInformation("Begin Render"); //Trace.TraceInformation("Begin Render");
var size = GetDimensions(); var size = GetDimensions();
var bitmap = new Bitmap((int)Math.Round(size.Width), (int)Math.Round(size.Height)); Bitmap bitmap = null;
// bitmap.SetResolution(300, 300); try
{
bitmap = new Bitmap((int) Math.Round(size.Width), (int) Math.Round(size.Height));
}
catch (ArgumentException e)
{
//When processing too many files at one the system can run out of memory
throw new SvgMemoryException("Cannot process SVG file, cannot allocate the required memory", e);
}
// bitmap.SetResolution(300, 300);
try try
{ {
Draw(bitmap); Draw(bitmap);
......
...@@ -284,7 +284,7 @@ namespace Svg ...@@ -284,7 +284,7 @@ namespace Svg
get { return this._customAttributes; } get { return this._customAttributes; }
} }
private static readonly Matrix _zeroMatrix = new Matrix(0, 0, 0, 0, 0, 0); private readonly Matrix _zeroMatrix = new Matrix(0, 0, 0, 0, 0, 0);
/// <summary> /// <summary>
/// Applies the required transforms to <see cref="ISvgRenderer"/>. /// Applies the required transforms to <see cref="ISvgRenderer"/>.
......
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Drawing; using System.Drawing;
...@@ -58,15 +59,15 @@ namespace Svg ...@@ -58,15 +59,15 @@ namespace Svg
public SizeF MeasureString(ISvgRenderer renderer, string text) public SizeF MeasureString(ISvgRenderer renderer, string text)
{ {
var g = GetGraphics(renderer); var g = GetGraphics(renderer);
StringFormat format = StringFormat.GenericTypographic; StringFormat format = StringFormat.GenericTypographic.Clone() as StringFormat;
format.SetMeasurableCharacterRanges(new CharacterRange[] { new CharacterRange(0, text.Length) }); format.SetMeasurableCharacterRanges(new CharacterRange[] {new CharacterRange(0, text.Length)});
format.FormatFlags |= StringFormatFlags.MeasureTrailingSpaces; format.FormatFlags |= StringFormatFlags.MeasureTrailingSpaces;
Region[] r = g.MeasureCharacterRanges(text, _font, new Rectangle(0, 0, 1000, 1000), format); Region[] r = g.MeasureCharacterRanges(text, _font, new Rectangle(0, 0, 1000, 1000), format);
RectangleF rect = r[0].GetBounds(g); RectangleF rect = r[0].GetBounds(g);
return new SizeF(rect.Width, Ascent(renderer)); return new SizeF(rect.Width, Ascent(renderer));
} }
private Graphics _graphics; private Graphics _graphics;
private Graphics GetGraphics(object renderer) private Graphics GetGraphics(object renderer)
......
...@@ -6,6 +6,7 @@ using System.IO; ...@@ -6,6 +6,7 @@ using System.IO;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Xml; using System.Xml;
using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.VisualStudio.TestTools.UnitTesting;
using Svg.Exceptions;
namespace Svg.UnitTests namespace Svg.UnitTests
{ {
...@@ -34,13 +35,29 @@ namespace Svg.UnitTests ...@@ -34,13 +35,29 @@ namespace Svg.UnitTests
public void TestMultiThread() public void TestMultiThread()
{ {
bool valid = true; bool valid = true;
Parallel.For(0, 3, (x) => Parallel.For(0, 10, (x) =>
{ {
LoadFile(); LoadFile();
}); });
Assert.IsTrue(valid, "One or more of the runs was invalid");
Trace.WriteLine("Done"); Trace.WriteLine("Done");
} }
[TestMethod]
[ExpectedException(typeof(SvgMemoryException))]
public void SVGGivesMemoryExceptionOnTooManyParallelTest()
{
try
{
Parallel.For(0, 50, (x) =>
{
LoadFile();
});
}
catch (AggregateException ex)
{
throw ex.InnerException;
}
}
private void LoadFile() private void LoadFile()
{ {
var xml = GetXMLDoc(); var xml = GetXMLDoc();
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment