Commit 0860e3de authored by Tebjan Halm's avatar Tebjan Halm Committed by GitHub
Browse files

Merge pull request #282 from mrbean-bremen/master

Add transform to bounds calculation in path based objects
parents f6622b55 3f1da2c7
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.
/// </summary>
[SvgElement("circle")]
public class SvgCircle : SvgVisualElement
public class SvgCircle : SvgPathBasedElement
{
private GraphicsPath _path;
......@@ -75,15 +68,6 @@ namespace Svg
}
}
/// <summary>
/// Gets the bounds of the circle.
/// </summary>
/// <value>The rectangular bounds of the circle.</value>
public override RectangleF Bounds
{
get { return this.Path(null).GetBounds(); }
}
/// <summary>
/// Gets the <see cref="GraphicsPath"/> representing this element.
/// </summary>
......
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.
/// </summary>
[SvgElement("ellipse")]
public class SvgEllipse : SvgVisualElement
public class SvgEllipse : SvgPathBasedElement
{
private SvgUnit _radiusX;
private SvgUnit _radiusY;
......@@ -80,15 +74,6 @@ namespace Svg
}
}
/// <summary>
/// Gets the bounds of the element.
/// </summary>
/// <value>The bounds.</value>
public override RectangleF Bounds
{
get { return this.Path(null).GetBounds(); }
}
/// <summary>
/// Gets the <see cref="GraphicsPath"/> for this element.
/// </summary>
......
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.
/// </summary>
[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<SvgLine>();
......
using System.Drawing.Drawing2D;
namespace Svg
{
/// <summary>
/// Represents an element that is using a GraphicsPath as rendering base.
/// </summary>
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();
}
}
}
}
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.
/// </summary>
[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<SvgPolygon>();
......
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.
/// </summary>
[SvgElement("rect")]
public class SvgRectangle : SvgVisualElement
public class SvgRectangle : SvgPathBasedElement
{
private SvgUnit _cornerRadiusX;
private SvgUnit _cornerRadiusY;
......@@ -168,15 +167,6 @@ namespace Svg
}
}
/// <summary>
/// Gets the bounds of the element.
/// </summary>
/// <value>The bounds.</value>
public override RectangleF Bounds
{
get { return Path(null).GetBounds(); }
}
/// <summary>
/// Gets the <see cref="GraphicsPath"/> for this element.
/// </summary>
......
......@@ -89,6 +89,7 @@
</ItemGroup>
<ItemGroup>
<Compile Include="Basic Shapes\SvgImage.cs" />
<Compile Include="Basic Shapes\SvgPathBasedElement.cs" />
<Compile Include="Basic Shapes\SvgVisualElement.cs" />
<Compile Include="Basic Shapes\SvgCircle.cs" />
<Compile Include="Basic Shapes\SvgEllipse.cs" />
......
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;
}
/// <summary>
/// Gets the bounds of the element.
/// </summary>
/// <value>The bounds.</value>
public override System.Drawing.RectangleF Bounds
{
get { return this.Path(null).GetBounds(); }
}
/// <summary>
/// Initializes a new instance of the <see cref="SvgGlyph"/> class.
/// </summary>
......
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Drawing;
namespace Svg.UnitTests
{
/// <summary>
/// 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.
/// </summary>
[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<SvgVisualElement>(elementId);
}
}
}
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" x="0px" y="0px" viewBox="0 0 100 100" enable-background="new 0 0 34.06945 33.11168" xml:space="preserve" id="svg2">
<defs id="defs30"/>
<g id="lines">
<line id="line" x1="10" x2="30" y1="20" y2="40" />
<line id="line-xlate" x1="10" x2="30" y1="20" y2="40" transform="translate(5, 5)" />
<line id="line-xform" x1="10" x2="30" y1="20" y2="40" transform="rotate(180), translate(-50, 0)" />
</g>
<g id="rects">
<rect id="rect" x="10" y="30" width="10" height="20" />
<rect id="rect-xlate" x="10" y="30" width="10" height="20" transform="translate(10, 10)" />
<rect id="rect-rot" x="10" y="30" width="10" height="20" transform="rotate(90)" />
</g>
</svg>
......@@ -54,6 +54,7 @@
</CodeAnalysisDependentAssemblyPaths>
</ItemGroup>
<ItemGroup>
<Compile Include="BoundsTests.cs" />
<Compile Include="CssQueryTest.cs" />
<Compile Include="LargeEmbeddedImageTest.cs" />
<Compile Include="MarkerEndTest.cs" />
......@@ -95,6 +96,9 @@
<ItemGroup>
<EmbeddedResource Include="Resources\Issue_TextElement\Text.svg" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Resources\Issue281_Bounds\BoundsTest.svg" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
......
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