SvgPath.cs 5.77 KB
Newer Older
davescriven's avatar
davescriven committed
1
2
3
4
5
6
7
8
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Xml.Serialization;
using System.Xml;
using System.Diagnostics;
9
using Svg.ExtensionMethods;
davescriven's avatar
davescriven committed
10
using Svg.Pathing;
owaits's avatar
owaits committed
11
using Svg.Transforms;
davescriven's avatar
davescriven committed
12
13
14

namespace Svg
{
15
16
17
    /// <summary>
    /// Represents an SVG path element.
    /// </summary>
18
    [SvgElement("path")]
19
    public class SvgPath : SvgVisualElement
davescriven's avatar
davescriven committed
20
21
22
    {
        private GraphicsPath _path;

23
24
25
        /// <summary>
        /// Gets or sets a <see cref="SvgPathSegmentList"/> of path data.
        /// </summary>
Eric Domke's avatar
Eric Domke committed
26
        [SvgAttribute("d", true)]
davescriven's avatar
davescriven committed
27
28
        public SvgPathSegmentList PathData
        {
29
        	get { return this.Attributes.GetAttribute<SvgPathSegmentList>("d"); }
30
31
32
33
34
35
            set
            {
            	this.Attributes["d"] = value;
            	value._owner = this;
                this.IsPathDirty = true;
            }
davescriven's avatar
davescriven committed
36
37
        }

38
39
40
        /// <summary>
        /// Gets or sets the length of the path.
        /// </summary>
Eric Domke's avatar
Eric Domke committed
41
        [SvgAttribute("pathLength", true)]
Eric Domke's avatar
Eric Domke committed
42
        public float PathLength
davescriven's avatar
davescriven committed
43
        {
Eric Domke's avatar
Eric Domke committed
44
            get { return this.Attributes.GetAttribute<float>("pathLength"); }
45
            set { this.Attributes["pathLength"] = value; }
davescriven's avatar
davescriven committed
46
47
        }

48
49
50
51
		
        /// <summary>
        /// Gets or sets the marker (end cap) of the path.
        /// </summary>
Eric Domke's avatar
Eric Domke committed
52
        [SvgAttribute("marker-end", true)]
53
		public Uri MarkerEnd
54
        {
55
			get { return this.Attributes.GetAttribute<Uri>("marker-end").ReplaceWithNullIfNone(); }
56
57
			set { this.Attributes["marker-end"] = value; }
		}
58
59


60
61
62
		/// <summary>
		/// Gets or sets the marker (start cap) of the path.
		/// </summary>
Eric Domke's avatar
Eric Domke committed
63
        [SvgAttribute("marker-mid", true)]
64
65
		public Uri MarkerMid
		{
66
			get { return this.Attributes.GetAttribute<Uri>("marker-mid").ReplaceWithNullIfNone(); }
67
68
			set { this.Attributes["marker-mid"] = value; }
		}
69
70


71
72
73
		/// <summary>
		/// Gets or sets the marker (start cap) of the path.
		/// </summary>
Eric Domke's avatar
Eric Domke committed
74
        [SvgAttribute("marker-start", true)]
75
76
		public Uri MarkerStart
		{
77
			get { return this.Attributes.GetAttribute<Uri>("marker-start").ReplaceWithNullIfNone(); }
78
79
			set { this.Attributes["marker-start"] = value; }
		}
80
81


davescriven's avatar
davescriven committed
82
83
84
        /// <summary>
        /// Gets the <see cref="GraphicsPath"/> for this element.
        /// </summary>
Eric Domke's avatar
Eric Domke committed
85
        public override GraphicsPath Path(ISvgRenderer renderer)
davescriven's avatar
davescriven committed
86
        {
87
            if (this._path == null || this.IsPathDirty)
davescriven's avatar
davescriven committed
88
            {
89
                _path = new GraphicsPath();
davescriven's avatar
davescriven committed
90

91
92
93
                foreach (SvgPathSegment segment in this.PathData)
                {
                    segment.AddToPath(_path);
davescriven's avatar
davescriven committed
94
                }
95
96

                this.IsPathDirty = false;
97
            }
98
            return _path;
davescriven's avatar
davescriven committed
99
100
101
102
103
        }

        internal void OnPathUpdated()
        {
            this.IsPathDirty = true;
104
            OnAttributeChanged(new AttributeEventArgs{ Attribute = "d", Value = this.Attributes.GetAttribute<SvgPathSegmentList>("d") });
davescriven's avatar
davescriven committed
105
106
        }

107
108
109
        /// <summary>
        /// Gets or sets a value to determine if anti-aliasing should occur when the element is being rendered.
        /// </summary>
davescriven's avatar
davescriven committed
110
111
112
113
114
        protected override bool RequiresSmoothRendering
        {
            get { return true; }
        }

115
116
117
        /// <summary>
        /// Gets the bounds of the element.
        /// </summary>
Tebjan Halm's avatar
Tebjan Halm committed
118
119
        /// <value>The bounds.</value>
        public override System.Drawing.RectangleF Bounds
davescriven's avatar
davescriven committed
120
        {
Tebjan Halm's avatar
Tebjan Halm committed
121
            get { return this.Path(null).GetBounds(); }
davescriven's avatar
davescriven committed
122
123
        }

124
125
126
        /// <summary>
        /// Initializes a new instance of the <see cref="SvgPath"/> class.
        /// </summary>
davescriven's avatar
davescriven committed
127
128
        public SvgPath()
        {
129
130
131
            var pathData = new SvgPathSegmentList();
            this.Attributes["d"] = pathData;
            pathData._owner = this;
davescriven's avatar
davescriven committed
132
        }
133

134
		/// <summary>
Eric Domke's avatar
Eric Domke committed
135
		/// Renders the stroke of the <see cref="SvgVisualElement"/> to the specified <see cref="ISvgRenderer"/>
136
		/// </summary>
Eric Domke's avatar
Eric Domke committed
137
		/// <param name="renderer">The <see cref="ISvgRenderer"/> object to render to.</param>
Eric Domke's avatar
Eric Domke committed
138
		protected internal override bool RenderStroke(ISvgRenderer renderer)
139
		{
Eric Domke's avatar
Eric Domke committed
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
            var result = base.RenderStroke(renderer);
            var path = this.Path(renderer);

            if (this.MarkerStart != null)
            {
                SvgMarker marker = this.OwnerDocument.GetElementById<SvgMarker>(this.MarkerStart.ToString());
                marker.RenderMarker(renderer, this, path.PathPoints[0], path.PathPoints[0], path.PathPoints[1]);
            }

            if (this.MarkerMid != null)
            {
                SvgMarker marker = this.OwnerDocument.GetElementById<SvgMarker>(this.MarkerMid.ToString());
                for (int i = 1; i <= path.PathPoints.Length - 2; i++)
                    marker.RenderMarker(renderer, this, path.PathPoints[i], path.PathPoints[i - 1], path.PathPoints[i], path.PathPoints[i + 1]);
            }

            if (this.MarkerEnd != null)
            {
                SvgMarker marker = this.OwnerDocument.GetElementById<SvgMarker>(this.MarkerEnd.ToString());
                marker.RenderMarker(renderer, this, path.PathPoints[path.PathPoints.Length - 1], path.PathPoints[path.PathPoints.Length - 2], path.PathPoints[path.PathPoints.Length - 1]);
            }
                
            return result;
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
		}

		public override SvgElement DeepCopy()
		{
			return DeepCopy<SvgPath>();
		}

		public override SvgElement DeepCopy<T>()
		{
			var newObj = base.DeepCopy<T>() as SvgPath;
			foreach (var pathData in this.PathData)
				newObj.PathData.Add(pathData.Clone());
			newObj.PathLength = this.PathLength;
			newObj.MarkerStart = this.MarkerStart;
			newObj.MarkerEnd = this.MarkerEnd;
			return newObj;

		}
davescriven's avatar
davescriven committed
181
182
    }
}