SvgPath.cs 5.5 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 the bounds of the element.
        /// </summary>
Tebjan Halm's avatar
Tebjan Halm committed
110
111
        /// <value>The bounds.</value>
        public override System.Drawing.RectangleF Bounds
davescriven's avatar
davescriven committed
112
        {
Tebjan Halm's avatar
Tebjan Halm committed
113
            get { return this.Path(null).GetBounds(); }
davescriven's avatar
davescriven committed
114
115
        }

116
117
118
        /// <summary>
        /// Initializes a new instance of the <see cref="SvgPath"/> class.
        /// </summary>
davescriven's avatar
davescriven committed
119
120
        public SvgPath()
        {
121
122
123
            var pathData = new SvgPathSegmentList();
            this.Attributes["d"] = pathData;
            pathData._owner = this;
davescriven's avatar
davescriven committed
124
        }
125

126
		/// <summary>
Eric Domke's avatar
Eric Domke committed
127
		/// Renders the stroke of the <see cref="SvgVisualElement"/> to the specified <see cref="ISvgRenderer"/>
128
		/// </summary>
Eric Domke's avatar
Eric Domke committed
129
		/// <param name="renderer">The <see cref="ISvgRenderer"/> object to render to.</param>
Eric Domke's avatar
Eric Domke committed
130
		protected internal override bool RenderStroke(ISvgRenderer renderer)
131
		{
Eric Domke's avatar
Eric Domke committed
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
            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;
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
		}

		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
173
174
    }
}