Commit 13132300 authored by Tebjan Halm's avatar Tebjan Halm
Browse files

Merge pull request #97 from articulate/BoundsPerformance

Performance Improvement
parents a653b4a4 1b8cb43f
...@@ -78,10 +78,10 @@ namespace Svg ...@@ -78,10 +78,10 @@ namespace Svg
/// <summary> /// <summary>
/// Gets the bounds of the circle. /// Gets the bounds of the circle.
/// </summary> /// </summary>
/// <value>The rectangular bounds of the circle.</value> /// <returns>The rectangular bounds of the circle.</returns>
public override RectangleF Bounds public override RectangleF CalculateBounds()
{ {
get { return this.Path(null).GetBounds(); } return this.Path(null).GetBounds();
} }
/// <summary> /// <summary>
......
...@@ -92,10 +92,10 @@ namespace Svg ...@@ -92,10 +92,10 @@ namespace Svg
/// <summary> /// <summary>
/// Gets the bounds of the element. /// Gets the bounds of the element.
/// </summary> /// </summary>
/// <value>The bounds.</value> /// <returns>The bounds.</returns>
public override RectangleF Bounds public override RectangleF CalculateBounds()
{ {
get { return this.Path(null).GetBounds(); } return this.Path(null).GetBounds();
} }
/// <summary> /// <summary>
......
...@@ -76,21 +76,21 @@ namespace Svg ...@@ -76,21 +76,21 @@ namespace Svg
{ {
get { return this.Attributes.GetAttribute<Uri>("href"); } get { return this.Attributes.GetAttribute<Uri>("href"); }
set { this.Attributes["href"] = value; } set { this.Attributes["href"] = value; }
} }
/// <summary> /// <summary>
/// Gets the bounds of the element. /// Gets the bounds of the element.
/// </summary> /// </summary>
/// <value>The bounds.</value> /// <returns>The bounds.</returns>
public override RectangleF Bounds public override RectangleF CalculateBounds()
{ {
get { return new RectangleF(this.Location.ToDeviceValue(null, this), return new RectangleF(this.Location.ToDeviceValue(null, this),
new SizeF(this.Width.ToDeviceValue(null, UnitRenderingType.Horizontal, this), new SizeF(this.Width.ToDeviceValue(null, UnitRenderingType.Horizontal, this),
this.Height.ToDeviceValue(null, UnitRenderingType.Vertical, this))); } this.Height.ToDeviceValue(null, UnitRenderingType.Vertical, this)));
} }
/// <summary> /// <summary>
/// Gets the <see cref="GraphicsPath"/> for this element. /// Gets the <see cref="GraphicsPath"/> for this element.
/// </summary> /// </summary>
......
...@@ -171,9 +171,9 @@ namespace Svg ...@@ -171,9 +171,9 @@ namespace Svg
return result; return result;
} }
public override System.Drawing.RectangleF Bounds public override RectangleF CalculateBounds()
{ {
get { return this.Path(null).GetBounds(); } return this.Path(null).GetBounds();
} }
public override SvgElement DeepCopy() public override SvgElement DeepCopy()
......
...@@ -130,9 +130,9 @@ namespace Svg ...@@ -130,9 +130,9 @@ namespace Svg
return result; return result;
} }
public override RectangleF Bounds public override RectangleF CalculateBounds()
{ {
get { return this.Path(null).GetBounds(); } return this.Path(null).GetBounds();
} }
......
...@@ -165,10 +165,10 @@ namespace Svg ...@@ -165,10 +165,10 @@ namespace Svg
/// <summary> /// <summary>
/// Gets the bounds of the element. /// Gets the bounds of the element.
/// </summary> /// </summary>
/// <value>The bounds.</value> /// <returns>The bounds.</returns>
public override RectangleF Bounds public override RectangleF CalculateBounds()
{ {
get { return Path(null).GetBounds(); } return Path(null).GetBounds();
} }
/// <summary> /// <summary>
......
...@@ -19,27 +19,11 @@ namespace Svg ...@@ -19,27 +19,11 @@ namespace Svg
/// </summary> /// </summary>
public abstract GraphicsPath Path(ISvgRenderer renderer); public abstract GraphicsPath Path(ISvgRenderer renderer);
PointF ISvgBoundable.Location
{
get
{
return Bounds.Location;
}
}
SizeF ISvgBoundable.Size
{
get
{
return Bounds.Size;
}
}
/// <summary> /// <summary>
/// Gets the bounds of the element. /// Gets the bounds of the element.
/// </summary> /// </summary>
/// <value>The bounds.</value> /// <returns>The bounds.</returns>
public abstract RectangleF Bounds { get; } public abstract RectangleF CalculateBounds();
/// <summary> /// <summary>
/// Gets the associated <see cref="SvgClipPath"/> if one has been specified. /// Gets the associated <see cref="SvgClipPath"/> if one has been specified.
......
...@@ -149,7 +149,7 @@ namespace Svg ...@@ -149,7 +149,7 @@ namespace Svg
break; break;
} }
System.Drawing.SizeF size = boundable.Bounds.Size; System.Drawing.SizeF size = boundable.CalculateBounds().Size;
switch (renderType) switch (renderType)
{ {
...@@ -157,13 +157,13 @@ namespace Svg ...@@ -157,13 +157,13 @@ namespace Svg
_deviceValue = (size.Width / 100) * value; _deviceValue = (size.Width / 100) * value;
break; break;
case UnitRenderingType.HorizontalOffset: case UnitRenderingType.HorizontalOffset:
_deviceValue = (size.Width / 100) * value + boundable.Location.X; _deviceValue = (size.Width / 100) * value + boundable.CalculateBounds().Location.X;
break; break;
case UnitRenderingType.Vertical: case UnitRenderingType.Vertical:
_deviceValue = (size.Height / 100) * value; _deviceValue = (size.Height / 100) * value;
break; break;
case UnitRenderingType.VerticalOffset: case UnitRenderingType.VerticalOffset:
_deviceValue = (size.Height / 100) * value + boundable.Location.Y; _deviceValue = (size.Height / 100) * value + boundable.CalculateBounds().Location.Y;
break; break;
default: default:
_deviceValue = (float)(Math.Sqrt(Math.Pow(size.Width, 2) + Math.Pow(size.Height, 2)) / Math.Sqrt(2) * value / 100.0); _deviceValue = (float)(Math.Sqrt(Math.Pow(size.Width, 2) + Math.Pow(size.Height, 2)) / Math.Sqrt(2) * value / 100.0);
......
...@@ -15,28 +15,9 @@ namespace Svg ...@@ -15,28 +15,9 @@ namespace Svg
/// </summary> /// </summary>
public static readonly Uri Namespace = new Uri("http://www.w3.org/2000/svg"); public static readonly Uri Namespace = new Uri("http://www.w3.org/2000/svg");
PointF ISvgBoundable.Location RectangleF ISvgBoundable.CalculateBounds()
{ {
get return new RectangleF(PointF.Empty, GetDimensions());
{
return PointF.Empty;
}
}
SizeF ISvgBoundable.Size
{
get
{
return GetDimensions();
}
}
RectangleF ISvgBoundable.Bounds
{
get
{
return new RectangleF(((ISvgBoundable)this).Location, ((ISvgBoundable)this).Size);
}
} }
private SvgUnit _x; private SvgUnit _x;
...@@ -185,32 +166,29 @@ namespace Svg ...@@ -185,32 +166,29 @@ namespace Svg
break; break;
} }
} }
/// <summary> /// <summary>
/// Gets the <see cref="GraphicsPath"/> for this element. /// Gets the <see cref="GraphicsPath"/> for this element.
/// </summary> /// </summary>
/// <value></value> /// <value></value>
public GraphicsPath Path public GraphicsPath CreatePath()
{ {
get var path = new GraphicsPath();
{
var path = new GraphicsPath();
AddPaths(this, path); AddPaths(this, path);
return path; return path;
}
} }
/// <summary> /// <summary>
/// Gets the bounds of the svg element. /// Gets the bounds of the svg element.
/// </summary> /// </summary>
/// <value>The bounds.</value> /// <returns>The bounds.</returns>
public RectangleF Bounds public RectangleF CalculateBounds()
{ {
get using (var path = CreatePath())
{ {
return this.Path.GetBounds(); return path.GetBounds();
} }
} }
...@@ -242,7 +220,7 @@ namespace Svg ...@@ -242,7 +220,7 @@ namespace Svg
} }
else else
{ {
bounds = this.Bounds; //do just one call to the recursive bounds property bounds = this.CalculateBounds(); //do just one call to the expensive bounds calculation method
} }
} }
......
...@@ -21,35 +21,32 @@ namespace Svg ...@@ -21,35 +21,32 @@ namespace Svg
/// <summary> /// <summary>
/// Gets the bounds of the element. /// Gets the bounds of the element.
/// </summary> /// </summary>
/// <value>The bounds.</value> /// <returns>The bounds.</returns>
public override System.Drawing.RectangleF Bounds public override RectangleF CalculateBounds()
{ {
get var r = new RectangleF();
{ foreach (var c in this.Children)
var r = new RectangleF(); {
foreach(var c in this.Children) if (c is SvgVisualElement)
{ {
if (c is SvgVisualElement) // First it should check if rectangle is empty or it will return the wrong Bounds.
// This is because when the Rectangle is Empty, the Union method adds as if the first values where X=0, Y=0
if (r.IsEmpty)
{ {
// First it should check if rectangle is empty or it will return the wrong Bounds. r = ((SvgVisualElement) c).CalculateBounds();
// This is because when the Rectangle is Empty, the Union method adds as if the first values where X=0, Y=0 }
if (r.IsEmpty) else
{ {
r = ((SvgVisualElement)c).Bounds; var childBounds = ((SvgVisualElement) c).CalculateBounds();
} if (!childBounds.IsEmpty)
else
{ {
var childBounds = ((SvgVisualElement)c).Bounds; r = RectangleF.Union(r, childBounds);
if (!childBounds.IsEmpty)
{
r = RectangleF.Union(r, childBounds);
}
} }
} }
} }
return r;
} }
return r;
} }
protected override bool Renderable { get { return false; } } protected override bool Renderable { get { return false; } }
......
...@@ -25,35 +25,32 @@ namespace Svg ...@@ -25,35 +25,32 @@ namespace Svg
/// <summary> /// <summary>
/// Gets the bounds of the element. /// Gets the bounds of the element.
/// </summary> /// </summary>
/// <value>The bounds.</value> /// <returns>The bounds.</returns>
public override System.Drawing.RectangleF Bounds public override RectangleF CalculateBounds()
{ {
get var r = new RectangleF();
foreach (var c in this.Children)
{ {
var r = new RectangleF(); if (c is SvgVisualElement)
foreach (var c in this.Children)
{ {
if (c is SvgVisualElement) // First it should check if rectangle is empty or it will return the wrong Bounds.
// This is because when the Rectangle is Empty, the Union method adds as if the first values where X=0, Y=0
if (r.IsEmpty)
{ {
// First it should check if rectangle is empty or it will return the wrong Bounds. r = ((SvgVisualElement) c).CalculateBounds();
// This is because when the Rectangle is Empty, the Union method adds as if the first values where X=0, Y=0 }
if (r.IsEmpty) else
{ {
r = ((SvgVisualElement)c).Bounds; var childBounds = ((SvgVisualElement) c).CalculateBounds();
} if (!childBounds.IsEmpty)
else
{ {
var childBounds = ((SvgVisualElement)c).Bounds; r = RectangleF.Union(r, childBounds);
if (!childBounds.IsEmpty)
{
r = RectangleF.Union(r, childBounds);
}
} }
} }
} }
return r;
} }
return r;
} }
/// <summary> /// <summary>
......
...@@ -48,34 +48,31 @@ namespace Svg.Document_Structure ...@@ -48,34 +48,31 @@ namespace Svg.Document_Structure
/// Gets the bounds of the element. /// Gets the bounds of the element.
/// </summary> /// </summary>
/// <value>The bounds.</value> /// <value>The bounds.</value>
public override System.Drawing.RectangleF Bounds public override System.Drawing.RectangleF CalculateBounds()
{ {
get var r = new RectangleF();
foreach (var c in this.Children)
{ {
var r = new RectangleF(); if (c is SvgVisualElement)
foreach (var c in this.Children)
{ {
if (c is SvgVisualElement) // First it should check if rectangle is empty or it will return the wrong Bounds.
// This is because when the Rectangle is Empty, the Union method adds as if the first values where X=0, Y=0
if (r.IsEmpty)
{ {
// First it should check if rectangle is empty or it will return the wrong Bounds. r = ((SvgVisualElement)c).CalculateBounds();
// This is because when the Rectangle is Empty, the Union method adds as if the first values where X=0, Y=0 }
if (r.IsEmpty) else
{ {
r = ((SvgVisualElement)c).Bounds; var childBounds = ((SvgVisualElement)c).CalculateBounds();
} if (!childBounds.IsEmpty)
else
{ {
var childBounds = ((SvgVisualElement)c).Bounds; r = RectangleF.Union(r, childBounds);
if (!childBounds.IsEmpty)
{
r = RectangleF.Union(r, childBounds);
}
} }
} }
} }
return r;
} }
return r;
} }
protected override bool Renderable { get { return false; } } protected override bool Renderable { get { return false; } }
......
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Drawing;
using System.Text; using System.Text;
using System.Web; using System.Web;
using System.Xml; using System.Xml;
...@@ -61,9 +62,9 @@ namespace Svg ...@@ -61,9 +62,9 @@ namespace Svg
return (element != null) ? element.Path(renderer) : null; return (element != null) ? element.Path(renderer) : null;
} }
public override System.Drawing.RectangleF Bounds public override RectangleF CalculateBounds()
{ {
get { return new System.Drawing.RectangleF(); } return new System.Drawing.RectangleF();
} }
protected override bool Renderable { get { return false; } } protected override bool Renderable { get { return false; } }
......
...@@ -25,35 +25,32 @@ namespace Svg ...@@ -25,35 +25,32 @@ namespace Svg
/// <summary> /// <summary>
/// Gets the bounds of the element. /// Gets the bounds of the element.
/// </summary> /// </summary>
/// <value>The bounds.</value> /// <returns>The bounds.</returns>
public override System.Drawing.RectangleF Bounds public override RectangleF CalculateBounds()
{ {
get var r = new RectangleF();
foreach (var c in this.Children)
{ {
var r = new RectangleF(); if (c is SvgVisualElement)
foreach (var c in this.Children)
{ {
if (c is SvgVisualElement) // First it should check if rectangle is empty or it will return the wrong Bounds.
// This is because when the Rectangle is Empty, the Union method adds as if the first values where X=0, Y=0
if (r.IsEmpty)
{ {
// First it should check if rectangle is empty or it will return the wrong Bounds. r = ((SvgVisualElement) c).CalculateBounds();
// This is because when the Rectangle is Empty, the Union method adds as if the first values where X=0, Y=0 }
if (r.IsEmpty) else
{ {
r = ((SvgVisualElement)c).Bounds; var childBounds = ((SvgVisualElement) c).CalculateBounds();
} if (!childBounds.IsEmpty)
else
{ {
var childBounds = ((SvgVisualElement)c).Bounds; r = RectangleF.Union(r, childBounds);
if (!childBounds.IsEmpty)
{
r = RectangleF.Union(r, childBounds);
}
} }
} }
} }
return r;
} }
return r;
} }
protected override bool Renderable { get { return false; } } protected override bool Renderable { get { return false; } }
......
...@@ -19,19 +19,9 @@ namespace Svg ...@@ -19,19 +19,9 @@ namespace Svg
_rect = new RectangleF(x, y, width, height); _rect = new RectangleF(x, y, width, height);
} }
public System.Drawing.PointF Location public RectangleF CalculateBounds()
{ {
get { return _rect.Location; } return _rect;
}
public System.Drawing.SizeF Size
{
get { return _rect.Size; }
}
public System.Drawing.RectangleF Bounds
{
get { return _rect; }
} }
} }
} }
...@@ -4,19 +4,6 @@ namespace Svg ...@@ -4,19 +4,6 @@ namespace Svg
{ {
public interface ISvgBoundable public interface ISvgBoundable
{ {
PointF Location RectangleF CalculateBounds();
{
get;
}
SizeF Size
{
get;
}
RectangleF Bounds
{
get;
}
} }
} }
\ No newline at end of file
using System.Drawing;
namespace Svg
{
internal sealed class ImmutableBoundable : ISvgBoundable
{
private readonly RectangleF bounds;
public ImmutableBoundable(ISvgBoundable boundable)
{
bounds = boundable.CalculateBounds();
}
public RectangleF CalculateBounds()
{
return bounds;
}
}
}
\ No newline at end of file
...@@ -178,7 +178,7 @@ namespace Svg ...@@ -178,7 +178,7 @@ namespace Svg
for (int i = 0; i < colourBlends; i++) for (int i = 0; i < colourBlends; i++)
{ {
var currentStop = this.Stops[radial ? this.Stops.Count - 1 - actualStops : actualStops]; var currentStop = this.Stops[radial ? this.Stops.Count - 1 - actualStops : actualStops];
var boundWidth = renderer.GetBoundable().Bounds.Width; var boundWidth = renderer.GetBoundable().CalculateBounds().Width;
mergedOpacity = opacity * currentStop.GetOpacity(); mergedOpacity = opacity * currentStop.GetOpacity();
position = position =
......
...@@ -191,7 +191,7 @@ namespace Svg ...@@ -191,7 +191,7 @@ namespace Svg
private LinePoints PointsToMove(ISvgBoundable boundable, PointF specifiedStart, PointF specifiedEnd) private LinePoints PointsToMove(ISvgBoundable boundable, PointF specifiedStart, PointF specifiedEnd)
{ {
var bounds = boundable.Bounds; var bounds = boundable.CalculateBounds();
if (specifiedStart.X == specifiedEnd.X) if (specifiedStart.X == specifiedEnd.X)
{ {
return (bounds.Top < specifiedStart.Y && specifiedStart.Y < bounds.Bottom ? LinePoints.Start : LinePoints.None) | return (bounds.Top < specifiedStart.Y && specifiedStart.Y < bounds.Bottom ? LinePoints.Start : LinePoints.None) |
...@@ -227,7 +227,7 @@ namespace Svg ...@@ -227,7 +227,7 @@ namespace Svg
return new GradientPoints(specifiedStart, specifiedEnd); return new GradientPoints(specifiedStart, specifiedEnd);
} }
var bounds = boundable.Bounds; var bounds = boundable.CalculateBounds();
var effectiveStart = specifiedStart; var effectiveStart = specifiedStart;
var effectiveEnd = specifiedEnd; var effectiveEnd = specifiedEnd;
var intersectionPoints = CandidateIntersections(bounds, specifiedStart, specifiedEnd); var intersectionPoints = CandidateIntersections(bounds, specifiedStart, specifiedEnd);
......
...@@ -95,15 +95,12 @@ namespace Svg ...@@ -95,15 +95,12 @@ namespace Svg
return null; return null;
} }
public override System.Drawing.RectangleF Bounds public override RectangleF CalculateBounds()
{ {
get var path = this.Path(null);
{ if (path != null)
var path = this.Path(null); return path.GetBounds();
if (path != null) return new System.Drawing.RectangleF();
return path.GetBounds();
return new System.Drawing.RectangleF();
}
} }
public override SvgElement DeepCopy() public override SvgElement DeepCopy()
......
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