diff --git a/Source/Basic Shapes/SvgCircle.cs b/Source/Basic Shapes/SvgCircle.cs
index 0aa978563025d64845ad8d7f3c27960f2390c051..8c37c06fb819fb35c167fbff675407f775705825 100644
--- a/Source/Basic Shapes/SvgCircle.cs
+++ b/Source/Basic Shapes/SvgCircle.cs
@@ -1,11 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-using System.Drawing;
using System.Drawing.Drawing2D;
-using System.Xml;
-using System.Web.UI.WebControls;
-using System.ComponentModel;
namespace Svg
{
@@ -13,7 +6,7 @@ namespace Svg
/// An SVG element to render circles to the document.
///
[SvgElement("circle")]
- public class SvgCircle : SvgVisualElement
+ public class SvgCircle : SvgPathBasedElement
{
private GraphicsPath _path;
@@ -75,15 +68,6 @@ namespace Svg
}
}
- ///
- /// Gets the bounds of the circle.
- ///
- /// The rectangular bounds of the circle.
- public override RectangleF Bounds
- {
- get { return this.Path(null).GetBounds(); }
- }
-
///
/// Gets the representing this element.
///
diff --git a/Source/Basic Shapes/SvgEllipse.cs b/Source/Basic Shapes/SvgEllipse.cs
index 749585234a8411366ba28ffa064fd5c680de7451..443d11377c0c997b08e493b103e0539d4b1c39bc 100644
--- a/Source/Basic Shapes/SvgEllipse.cs
+++ b/Source/Basic Shapes/SvgEllipse.cs
@@ -1,10 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-using System.Drawing;
using System.Drawing.Drawing2D;
-using System.Xml;
-using System.ComponentModel;
namespace Svg
{
@@ -12,7 +6,7 @@ namespace Svg
/// Represents and SVG ellipse element.
///
[SvgElement("ellipse")]
- public class SvgEllipse : SvgVisualElement
+ public class SvgEllipse : SvgPathBasedElement
{
private SvgUnit _radiusX;
private SvgUnit _radiusY;
@@ -80,15 +74,6 @@ namespace Svg
}
}
- ///
- /// Gets the bounds of the element.
- ///
- /// The bounds.
- public override RectangleF Bounds
- {
- get { return this.Path(null).GetBounds(); }
- }
-
///
/// Gets the for this element.
///
diff --git a/Source/Basic Shapes/SvgLine.cs b/Source/Basic Shapes/SvgLine.cs
index 1ece3ee9ce991ca9dc99406a26ae8e8f5230a368..86c37aeee00484b3127f0dcd6f12bfdf0fce5edb 100644
--- a/Source/Basic Shapes/SvgLine.cs
+++ b/Source/Basic Shapes/SvgLine.cs
@@ -1,7 +1,4 @@
using System;
-using System.Collections.Generic;
-using System.Text;
-using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using Svg.ExtensionMethods;
@@ -12,7 +9,7 @@ namespace Svg
/// Represents and SVG line element.
///
[SvgElement("line")]
- public class SvgLine : SvgVisualElement
+ public class SvgLine : SvgPathBasedElement
{
private SvgUnit _startX;
private SvgUnit _startY;
@@ -186,11 +183,6 @@ namespace Svg
return result;
}
- public override System.Drawing.RectangleF Bounds
- {
- get { return this.Path(null).GetBounds(); }
- }
-
public override SvgElement DeepCopy()
{
return DeepCopy();
diff --git a/Source/Basic Shapes/SvgPathBasedElement.cs b/Source/Basic Shapes/SvgPathBasedElement.cs
new file mode 100644
index 0000000000000000000000000000000000000000..a1f7fcba6d773d0a6dc670547ee6fa59c4c3573f
--- /dev/null
+++ b/Source/Basic Shapes/SvgPathBasedElement.cs
@@ -0,0 +1,24 @@
+using System.Drawing.Drawing2D;
+
+namespace Svg
+{
+ ///
+ /// Represents an element that is using a GraphicsPath as rendering base.
+ ///
+ public abstract class SvgPathBasedElement : SvgVisualElement
+ {
+ public override System.Drawing.RectangleF Bounds
+ {
+ get
+ {
+ var path = this.Path(null);
+ if (Transforms != null && Transforms.Count > 0)
+ {
+ path = (GraphicsPath)path.Clone();
+ path.Transform(Transforms.GetMatrix());
+ }
+ return path.GetBounds();
+ }
+ }
+ }
+}
diff --git a/Source/Basic Shapes/SvgPolygon.cs b/Source/Basic Shapes/SvgPolygon.cs
index a2425c220cb46db8197b962a75c186e8f0e0dba6..a1201c924faeeb3f9cbd1a99f5ff965ea19e1b66 100644
--- a/Source/Basic Shapes/SvgPolygon.cs
+++ b/Source/Basic Shapes/SvgPolygon.cs
@@ -1,11 +1,7 @@
using System;
-using System.Collections.Generic;
-using System.Text;
-using System.Drawing;
using System.Drawing.Drawing2D;
using System.Diagnostics;
using Svg.ExtensionMethods;
-using Svg.Pathing;
namespace Svg
{
@@ -13,7 +9,7 @@ namespace Svg
/// SvgPolygon defines a closed shape consisting of a set of connected straight line segments.
///
[SvgElement("polygon")]
- public class SvgPolygon : SvgVisualElement
+ public class SvgPolygon : SvgPathBasedElement
{
private GraphicsPath _path;
@@ -136,12 +132,6 @@ namespace Svg
return result;
}
- public override RectangleF Bounds
- {
- get { return this.Path(null).GetBounds(); }
- }
-
-
public override SvgElement DeepCopy()
{
return DeepCopy();
diff --git a/Source/Basic Shapes/SvgRectangle.cs b/Source/Basic Shapes/SvgRectangle.cs
index 733272894cfb8a8847abc3c4dc80fcc3ea16a7a4..c2c894e1ecb2c55244fc8bb70442a48769b12866 100644
--- a/Source/Basic Shapes/SvgRectangle.cs
+++ b/Source/Basic Shapes/SvgRectangle.cs
@@ -1,7 +1,6 @@
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
-using Svg.Transforms;
namespace Svg
{
@@ -9,7 +8,7 @@ namespace Svg
/// Represents an SVG rectangle that could also have rounded edges.
///
[SvgElement("rect")]
- public class SvgRectangle : SvgVisualElement
+ public class SvgRectangle : SvgPathBasedElement
{
private SvgUnit _cornerRadiusX;
private SvgUnit _cornerRadiusY;
@@ -168,15 +167,6 @@ namespace Svg
}
}
- ///
- /// Gets the bounds of the element.
- ///
- /// The bounds.
- public override RectangleF Bounds
- {
- get { return Path(null).GetBounds(); }
- }
-
///
/// Gets the for this element.
///
diff --git a/Source/Svg.csproj b/Source/Svg.csproj
index c95eaedc327e2bc36476e2f9d1144e17d4e5138b..412c9bc2712e3be1de01ec317a9e8ee26951e5c3 100644
--- a/Source/Svg.csproj
+++ b/Source/Svg.csproj
@@ -89,6 +89,7 @@
+
diff --git a/Source/Text/SvgGlyph.cs b/Source/Text/SvgGlyph.cs
index 2517aba0b1d6af930697eb61da5893f43f9ddcc9..9245e9583b5631186456e6896c33f62d9b035903 100644
--- a/Source/Text/SvgGlyph.cs
+++ b/Source/Text/SvgGlyph.cs
@@ -1,14 +1,11 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
+using System.Linq;
using Svg.Pathing;
using System.Drawing.Drawing2D;
namespace Svg
{
[SvgElement("glyph")]
- public class SvgGlyph : SvgVisualElement
+ public class SvgGlyph : SvgPathBasedElement
{
private GraphicsPath _path;
@@ -79,15 +76,6 @@ namespace Svg
return _path;
}
- ///
- /// Gets the bounds of the element.
- ///
- /// The bounds.
- public override System.Drawing.RectangleF Bounds
- {
- get { return this.Path(null).GetBounds(); }
- }
-
///
/// Initializes a new instance of the class.
///
diff --git a/Tests/Svg.UnitTests/BoundsTests.cs b/Tests/Svg.UnitTests/BoundsTests.cs
new file mode 100644
index 0000000000000000000000000000000000000000..0e317b348068cea053a91b4f4a2ec9fc2731e645
--- /dev/null
+++ b/Tests/Svg.UnitTests/BoundsTests.cs
@@ -0,0 +1,68 @@
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System.Drawing;
+
+namespace Svg.UnitTests
+{
+ ///
+ /// Test class to test bounds for elements without vs. with transformations
+ /// (see issue 281). Only some basic elements are tested - this should be sufficient
+ /// to verify the functionality for all path-based elements.
+ ///
+ [TestClass]
+ public class BoundsTests : SvgTestHelper
+ {
+ private const string BoundsTestSvg = "Issue281_Bounds.BoundsTest.svg";
+ private static SvgDocument testDocument;
+
+ [TestMethod]
+ public void TestLineBounds()
+ {
+ // x1="10" x2="30" y1="20" y2="40", default line thickness is 1
+ AssertEqualBounds("line", 9.5f, 19.5f, 21, 21);
+ // additional translation(5, 5)
+ AssertEqualBounds("line-xlate", 14.5f, 24.5f, 21, 21);
+ // additional rotation(180) and translation(-50, 0)
+ AssertEqualBounds("line-xform", 19.5f, -40.5f, 21, 21);
+ }
+
+ [TestMethod]
+ public void TestRectangleBounds()
+ {
+ // x="10" y="30" width="10" height="20"
+ AssertEqualBounds("rect", 9.5f, 29.5f, 10.5f, 20.5f);
+ // additional translation(10, 10)
+ AssertEqualBounds("rect-xlate", 19.5f, 39.5f, 10.5f, 20.5f);
+ // additional rotation(90)
+ AssertEqualBounds("rect-rot", -50, 9.5f, 20.5f, 10.5f);
+ }
+
+ [TestMethod]
+ public void TestGroupBounds()
+ {
+ // all lines from TestLineBounds()
+ AssertEqualBounds("lines", 9.5f, 29.5f, 10.5f, 20.5f);
+ // all reactangles from TestRectangleBounds()
+ AssertEqualBounds("rects", 19.5f, 39.5f, 10.5f, 20.5f);
+ }
+
+ private void AssertEqualBounds(string elementId, float x, float y, float width, float height)
+ {
+ const float Epsilon = 0.01f;
+ var element = GetElement(elementId);
+ var elementBounds = element.Bounds;
+ Assert.AreEqual(x, elementBounds.X, Epsilon);
+ Assert.AreEqual(y, elementBounds.Y, Epsilon);
+ Assert.AreEqual(width, elementBounds.Width, Epsilon);
+ Assert.AreEqual(height, elementBounds.Height, Epsilon);
+ }
+
+ private SvgVisualElement GetElement(string elementId)
+ {
+ if (testDocument == null)
+ {
+ testDocument = OpenSvg(GetXMLDocFromResource(GetFullResourceString(BoundsTestSvg)));
+ }
+ return testDocument.GetElementById(elementId);
+ }
+ }
+}
diff --git a/Tests/Svg.UnitTests/Resources/Issue281_Bounds/BoundsTest.svg b/Tests/Svg.UnitTests/Resources/Issue281_Bounds/BoundsTest.svg
new file mode 100644
index 0000000000000000000000000000000000000000..1676c789f9781b03dfb5a029ca5e964dca4804c7
--- /dev/null
+++ b/Tests/Svg.UnitTests/Resources/Issue281_Bounds/BoundsTest.svg
@@ -0,0 +1,14 @@
+
+
diff --git a/Tests/Svg.UnitTests/Svg.UnitTests.csproj b/Tests/Svg.UnitTests/Svg.UnitTests.csproj
index 92f8e3349783b4efda069063dae53d3c7e24cd48..5be340478b49bbfdbf85a08fb804a467d849c5f2 100644
--- a/Tests/Svg.UnitTests/Svg.UnitTests.csproj
+++ b/Tests/Svg.UnitTests/Svg.UnitTests.csproj
@@ -54,6 +54,7 @@
+
@@ -95,6 +96,9 @@
+
+
+