SvgMarkerElement.cs 3.78 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
using Svg.ExtensionMethods;
using System;

namespace Svg
{
    /// <summary>
    /// Represents a path based element that can have markers.
    /// </summary>
    public abstract class SvgMarkerElement : SvgPathBasedElement
    {
        /// <summary>
        /// Gets or sets the marker (end cap) of the path.
        /// </summary>
        [SvgAttribute("marker-end", true)]
        public Uri MarkerEnd
        {
            get { return this.Attributes.GetAttribute<Uri>("marker-end").ReplaceWithNullIfNone(); }
            set { this.Attributes["marker-end"] = value; }
        }


        /// <summary>
23
        /// Gets or sets the marker (mid points) of the path.
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
        /// </summary>
        [SvgAttribute("marker-mid", true)]
        public Uri MarkerMid
        {
            get { return this.Attributes.GetAttribute<Uri>("marker-mid").ReplaceWithNullIfNone(); }
            set { this.Attributes["marker-mid"] = value; }
        }


        /// <summary>
        /// Gets or sets the marker (start cap) of the path.
        /// </summary>
        [SvgAttribute("marker-start", true)]
        public Uri MarkerStart
        {
            get { return this.Attributes.GetAttribute<Uri>("marker-start").ReplaceWithNullIfNone(); }
            set { this.Attributes["marker-start"] = value; }
        }

        /// <summary>
44
45
        /// Renders the stroke of the element to the specified <see cref="ISvgRenderer"/>.
        /// Includes rendering of all markers defined in attributes.
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
        /// </summary>
        /// <param name="renderer">The <see cref="ISvgRenderer"/> object to render to.</param>
        protected internal override bool RenderStroke(ISvgRenderer renderer)
        {
            var result = base.RenderStroke(renderer);
            var path = this.Path(renderer);
            var pathLength = path.PathPoints.Length;

            if (this.MarkerStart != null)
            {
                var refPoint1 = path.PathPoints[0];
                var index = 1;
                while (index < pathLength && path.PathPoints[index] == refPoint1)
                {
                    ++index;
                }
                var refPoint2 = path.PathPoints[index];
                SvgMarker marker = this.OwnerDocument.GetElementById<SvgMarker>(this.MarkerStart.ToString());
                marker.RenderMarker(renderer, this, refPoint1, refPoint1, refPoint2);
            }

            if (this.MarkerMid != null)
            {
                SvgMarker marker = this.OwnerDocument.GetElementById<SvgMarker>(this.MarkerMid.ToString());
70
                int bezierIndex = -1;
71
                for (int i = 1; i <= path.PathPoints.Length - 2; i++)
72
73
74
75
76
77
78
79
80
81
                {
                    // for Bezier curves, the marker shall only been shown at the last point
                    if ((path.PathTypes[i] & 7) == 3)
                        bezierIndex = (bezierIndex + 1) % 3;
                    else
                        bezierIndex = -1;
                    if (bezierIndex == -1 || bezierIndex == 2)
                        marker.RenderMarker(renderer, this, path.PathPoints[i], path.PathPoints[i - 1], path.PathPoints[i], path.PathPoints[i + 1]);

                }
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
            }

            if (this.MarkerEnd != null)
            {
                var index = pathLength - 1;
                var refPoint1 = path.PathPoints[index];
                --index;
                while (index > 0 && path.PathPoints[index] == refPoint1)
                {
                    --index;
                }
                var refPoint2 = path.PathPoints[index];
                SvgMarker marker = this.OwnerDocument.GetElementById<SvgMarker>(this.MarkerEnd.ToString());
                marker.RenderMarker(renderer, this, refPoint1, refPoint2, path.PathPoints[path.PathPoints.Length - 1]);
            }

            return result;
        }
    }
}