From c97ef1560a0dc29ccd4ad049cc0810014ec0c4e9 Mon Sep 17 00:00:00 2001 From: davescriven Date: Fri, 17 Oct 2008 23:48:03 +0000 Subject: [PATCH] - Applied patches 1944, 1955 and 1956. - Made all transforms (SvgTranslate, SvgMatrix etc) sealed types. --- Basic Shapes/SvgGraphicsElement.cs | 44 ++++++++++++++++++++++++- Clipping and Masking/ISvgClipable.cs | 9 +++-- Clipping and Masking/SvgClipPath.cs | 25 ++++++++++++-- DataTypes/SvgUnit.cs | 4 +++ Document Structure/SvgDocument.cs | 10 ++++++ Document Structure/SvgUse.cs | 17 +++++++++- Svg.csproj | 3 ++ SvgElementCollection.cs | 31 ++++++++++++++---- SvgElementIdManager.cs | 11 ++++++- SvgRenderer.cs | 11 +++++++ Transforms/SvgRotate.cs | 2 +- Transforms/SvgScale.cs | 2 +- Transforms/SvgTransformConverter.cs | 49 ++++++++++++++++++++++++++-- Transforms/SvgTranslate.cs | 2 +- 14 files changed, 199 insertions(+), 21 deletions(-) diff --git a/Basic Shapes/SvgGraphicsElement.cs b/Basic Shapes/SvgGraphicsElement.cs index 7f09b07..a9316cf 100644 --- a/Basic Shapes/SvgGraphicsElement.cs +++ b/Basic Shapes/SvgGraphicsElement.cs @@ -13,10 +13,11 @@ namespace Svg /// /// The class that all SVG elements should derive from when they are to be rendered. /// - public abstract partial class SvgGraphicsElement : SvgElement, ISvgStylable + public abstract partial class SvgGraphicsElement : SvgElement, ISvgStylable, ISvgClipable { private bool _dirty; private bool _requiresSmoothRendering; + private Region _previousClip; /// /// Gets the for this element. @@ -40,6 +41,16 @@ namespace Svg set { this._dirty = value; } } + /// + /// Gets the associated if one has been specified. + /// + [SvgAttribute("clip-path")] + public virtual Uri ClipPath + { + get { return this.Attributes.GetAttribute("clip-path"); } + set { this.Attributes["clip-path"] = value; } + } + /// /// Gets or sets a value to determine if anti-aliasing should occur when the element is being rendered. /// @@ -66,6 +77,7 @@ namespace Svg if (this.Path != null && this.Visible) { this.PushTransforms(renderer); + this.SetClip(renderer); // If this element needs smoothing enabled turn anti aliasing on if (this.RequiresSmoothRendering) @@ -104,8 +116,38 @@ namespace Svg renderer.SmoothingMode = SmoothingMode.Default; } + this.ResetClip(renderer); this.PopTransforms(renderer); } } + + protected internal virtual void SetClip(SvgRenderer renderer) + { + if (this.ClipPath != null) + { + SvgClipPath clipPath = this.OwnerDocument.GetElementById(this.ClipPath.ToString()); + this._previousClip = renderer.Clip; + renderer.SetClip(clipPath.GetClipRegion()); + } + } + + protected internal virtual void ResetClip(SvgRenderer renderer) + { + if (this.ClipPath != null) + { + renderer.SetClip(this._previousClip); + this._previousClip = null; + } + } + + void ISvgClipable.SetClip(SvgRenderer renderer) + { + this.SetClip(renderer); + } + + void ISvgClipable.ResetClip(SvgRenderer renderer) + { + this.ResetClip(renderer); + } } } \ No newline at end of file diff --git a/Clipping and Masking/ISvgClipable.cs b/Clipping and Masking/ISvgClipable.cs index 2536579..ff3b7dd 100644 --- a/Clipping and Masking/ISvgClipable.cs +++ b/Clipping and Masking/ISvgClipable.cs @@ -8,8 +8,11 @@ namespace Svg { public interface ISvgClipable { - SvgClipPath ClipPath { get; set; } - void SetClip(Graphics graphics); - void ResetClip(Graphics graphics); + /// + /// Gets or sets the ID of the associated if one has been specified. + /// + Uri ClipPath { get; set; } + void SetClip(SvgRenderer renderer); + void ResetClip(SvgRenderer renderer); } } \ No newline at end of file diff --git a/Clipping and Masking/SvgClipPath.cs b/Clipping and Masking/SvgClipPath.cs index 0977929..3d856fe 100644 --- a/Clipping and Masking/SvgClipPath.cs +++ b/Clipping and Masking/SvgClipPath.cs @@ -6,12 +6,18 @@ using System.Drawing.Drawing2D; namespace Svg { + /// + /// + /// public sealed class SvgClipPath : SvgElement { private SvgCoordinateUnits _clipPathUnits; private bool _pathDirty; private Region _region; + /// + /// + /// [SvgAttribute("clipPathUnits")] public SvgCoordinateUnits ClipPathUnits { @@ -27,7 +33,11 @@ namespace Svg this._clipPathUnits = SvgCoordinateUnits.ObjectBoundingBox; } - private Region GetClipRegion() + /// + /// Gets this 's region to be clipped. + /// + /// A new containing the area to be clipped. + protected internal Region GetClipRegion() { if (_region == null || _pathDirty) { @@ -44,18 +54,23 @@ namespace Svg return _region; } + /// + /// + /// + /// + /// private void ComplementRegion(Region region, SvgElement element) { SvgGraphicsElement graphicsElement = element as SvgGraphicsElement; - if (graphicsElement != null) + if (graphicsElement != null && graphicsElement.Path != null) { region.Complement(graphicsElement.Path); } foreach (SvgElement child in element.Children) { - ComplementRegion(region, element); + ComplementRegion(region, child); } } @@ -71,6 +86,10 @@ namespace Svg this._pathDirty = true; } + /// + /// Renders the and contents to the specified object. + /// + /// The object to render to. protected override void Render(SvgRenderer renderer) { // Do nothing diff --git a/DataTypes/SvgUnit.cs b/DataTypes/SvgUnit.cs index 40befbd..3346754 100644 --- a/DataTypes/SvgUnit.cs +++ b/DataTypes/SvgUnit.cs @@ -90,6 +90,10 @@ namespace Svg switch (this.Type) { + case SvgUnitType.Em: + float points = (float)(this.Value * 9); + _deviceValue = (points / 72) * ppi; + break; case SvgUnitType.Centimeter: _deviceValue = (float)((this.Value / cmInInch) * ppi); break; diff --git a/Document Structure/SvgDocument.cs b/Document Structure/SvgDocument.cs index 8e55f34..9056f92 100644 --- a/Document Structure/SvgDocument.cs +++ b/Document Structure/SvgDocument.cs @@ -93,6 +93,16 @@ namespace Svg return IdManager.GetElementById(id); } + /// + /// Retrieves the with the specified ID. + /// + /// A containing the ID of the element to find. + /// An of one exists with the specified ID; otherwise false. + public virtual TSvgElement GetElementById(string id) where TSvgElement : SvgElement + { + return (this.GetElementById(id) as TSvgElement); + } + /// /// Opens the document at the specified path and loads the contents. /// diff --git a/Document Structure/SvgUse.cs b/Document Structure/SvgUse.cs index b9ed59b..515caf6 100644 --- a/Document Structure/SvgUse.cs +++ b/Document Structure/SvgUse.cs @@ -46,7 +46,11 @@ namespace Svg public override System.Drawing.Drawing2D.GraphicsPath Path { - get { return null; } + get + { + SvgGraphicsElement element = (SvgGraphicsElement)this.OwnerDocument.IdManager.GetElementById(this.ReferencedElement); + return (element != null) ? element.Path : null; + } } public override System.Drawing.RectangleF Bounds @@ -54,6 +58,17 @@ namespace Svg get { return new System.Drawing.RectangleF(); } } + public override SvgElementCollection Children + { + get + { + SvgElement element = this.OwnerDocument.IdManager.GetElementById(this.ReferencedElement); + SvgElementCollection elements = new SvgElementCollection(this, true); + elements.Add(element); + return elements; + } + } + protected override void Render(SvgRenderer renderer) { this.PushTransforms(renderer); diff --git a/Svg.csproj b/Svg.csproj index 6e5ef31..b83ba77 100644 --- a/Svg.csproj +++ b/Svg.csproj @@ -135,8 +135,11 @@ + + + diff --git a/SvgElementCollection.cs b/SvgElementCollection.cs index d2bb9d8..dcf61ae 100644 --- a/SvgElementCollection.cs +++ b/SvgElementCollection.cs @@ -11,12 +11,19 @@ namespace Svg { private List _elements; private SvgElement _owner; + private bool _mock; /// /// Initialises a new instance of an class. /// /// The owner of the collection. internal SvgElementCollection(SvgElement owner) + : this(owner, false) + { + + } + + internal SvgElementCollection(SvgElement owner, bool mock) { if (owner == null) { @@ -25,6 +32,7 @@ namespace Svg this._elements = new List(); this._owner = owner; + this._mock = mock; } /// @@ -65,14 +73,19 @@ namespace Svg public void Add(SvgElement item) { - if (this._owner.OwnerDocument != null) + if (!this._mock) { - this._owner.OwnerDocument.IdManager.Add(item); + if (this._owner.OwnerDocument != null) + { + this._owner.OwnerDocument.IdManager.Add(item); + } + + item._parent = this._owner; } - this._elements.Add(item); - item._parent = this._owner; item._parent.OnElementAdded(item, this.Count - 1); + + this._elements.Add(item); } public void Clear() @@ -111,11 +124,15 @@ namespace Svg if (removed) { this._owner.OnElementRemoved(item); - item._parent = null; - if (this._owner.OwnerDocument != null) + if (!this._mock) { - this._owner.OwnerDocument.IdManager.Remove(item); + item._parent = null; + + if (this._owner.OwnerDocument != null) + { + this._owner.OwnerDocument.IdManager.Remove(item); + } } } diff --git a/SvgElementIdManager.cs b/SvgElementIdManager.cs index 2a77531..1956501 100644 --- a/SvgElementIdManager.cs +++ b/SvgElementIdManager.cs @@ -20,11 +20,20 @@ namespace Svg /// An of one exists with the specified ID; otherwise false. public virtual SvgElement GetElementById(string id) { + if (id.StartsWith("url(")) + { + id = id.Substring(4); + id = id.TrimEnd(')'); + } if (id.StartsWith("#")) { id = id.Substring(1); } - return this._idValueMap[id]; + + SvgElement element = null; + this._idValueMap.TryGetValue(id, out element); + + return element; } public virtual SvgElement GetElementById(Uri uri) diff --git a/SvgRenderer.cs b/SvgRenderer.cs index 1553901..c216e39 100644 --- a/SvgRenderer.cs +++ b/SvgRenderer.cs @@ -19,6 +19,12 @@ namespace Svg { } + public Region Clip + { + get { return this._innerGraphics.Clip; } + set { this._innerGraphics.Clip = value; } + } + /// /// Creates a new from the specified . /// @@ -30,6 +36,11 @@ namespace Svg return renderer; } + public void SetClip(Region region) + { + this._innerGraphics.SetClip(region, CombineMode.Union); + } + public void FillPath(Brush brush, GraphicsPath path) { this._innerGraphics.FillPath(brush, path); diff --git a/Transforms/SvgRotate.cs b/Transforms/SvgRotate.cs index 6d2310b..4743aae 100644 --- a/Transforms/SvgRotate.cs +++ b/Transforms/SvgRotate.cs @@ -4,7 +4,7 @@ using System.Text; namespace Svg.Transforms { - public class SvgRotate : SvgTransform + public sealed class SvgRotate : SvgTransform { private float angle; diff --git a/Transforms/SvgScale.cs b/Transforms/SvgScale.cs index 9be303a..1961e17 100644 --- a/Transforms/SvgScale.cs +++ b/Transforms/SvgScale.cs @@ -5,7 +5,7 @@ using System.Drawing.Drawing2D; namespace Svg.Transforms { - public class SvgScale : SvgTransform + public sealed class SvgScale : SvgTransform { private float scaleFactorX; private float scaleFactorY; diff --git a/Transforms/SvgTransformConverter.cs b/Transforms/SvgTransformConverter.cs index 15ae0b4..1bcff7f 100644 --- a/Transforms/SvgTransformConverter.cs +++ b/Transforms/SvgTransformConverter.cs @@ -20,7 +20,7 @@ namespace Svg.Transforms if (transforms[i] == ')') { yield return transforms.Substring(transformEnd, i - transformEnd + 1).Trim(); - transformEnd = i+1; + transformEnd = i + 1; } } } @@ -57,7 +57,7 @@ namespace Svg.Transforms switch (transformName) { case "translate": - string[] coords = contents.Split(new char[]{',', ' '}, StringSplitOptions.RemoveEmptyEntries); + string[] coords = contents.Split(new char[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries); if (coords.Length != 2) { @@ -92,6 +92,51 @@ namespace Svg.Transforms transformList.Add(new SvgScale(sx)); } + break; + case "matrix": + string[] points = contents.Split(new char[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries); + + if (points.Length != 6) + { + throw new FormatException("Matrix transforms must be in the format 'matrix(m11, m12, m21, m22, dx, dy)'"); + } + + List mPoints = new List(); + foreach (string point in points) + { + mPoints.Add(float.Parse(point.Trim(), NumberStyles.Float, CultureInfo.InvariantCulture)); + } + + transformList.Add(new SvgMatrix(mPoints)); + break; + case "shear": + string[] shears = contents.Split(new char[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries); + + if (shears.Length == 0 || shears.Length > 2) + { + throw new FormatException("Shear transforms must be in the format 'shear(x [,y])'"); + } + + float hx = float.Parse(shears[0].Trim(), NumberStyles.Float, CultureInfo.InvariantCulture); + + if (shears.Length > 1) + { + float hy = float.Parse(shears[1].Trim(), NumberStyles.Float, CultureInfo.InvariantCulture); + transformList.Add(new SvgShear(hx, hy)); + } + else + { + transformList.Add(new SvgShear(hx)); + } + + break; + case "skewX": + float ax = float.Parse(contents, NumberStyles.Float, CultureInfo.InvariantCulture); + transformList.Add(new SvgSkew(ax, 0)); + break; + case "skewY": + float ay = float.Parse(contents, NumberStyles.Float, CultureInfo.InvariantCulture); + transformList.Add(new SvgSkew(0, ay)); break; } } diff --git a/Transforms/SvgTranslate.cs b/Transforms/SvgTranslate.cs index d3a54e6..5e04a1d 100644 --- a/Transforms/SvgTranslate.cs +++ b/Transforms/SvgTranslate.cs @@ -4,7 +4,7 @@ using System.Text; namespace Svg.Transforms { - public class SvgTranslate : SvgTransform + public sealed class SvgTranslate : SvgTransform { private float x; private float y; -- GitLab