SvgClipPath.cs 3.76 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;

namespace Svg
{
9
    /// <summary>
10
    /// Defines a path that can be used by other <see cref="ISvgClipable"/> elements.
11
    /// </summary>
12
    [SvgElement("clipPath")]
davescriven's avatar
davescriven committed
13
14
    public sealed class SvgClipPath : SvgElement
    {
15
        private bool _pathDirty = true;
davescriven's avatar
davescriven committed
16

17
        /// <summary>
18
        /// Specifies the coordinate system for the clipping path.
19
        /// </summary>
davescriven's avatar
davescriven committed
20
        [SvgAttribute("clipPathUnits")]
21
        public SvgCoordinateUnits ClipPathUnits { get; set; }
davescriven's avatar
davescriven committed
22

23
24
25
        /// <summary>
        /// Initializes a new instance of the <see cref="SvgClipPath"/> class.
        /// </summary>
davescriven's avatar
davescriven committed
26
27
        public SvgClipPath()
        {
28
            this.ClipPathUnits = SvgCoordinateUnits.ObjectBoundingBox;
davescriven's avatar
davescriven committed
29
30
        }

31
32
        private GraphicsPath cachedClipPath = null;

33
        /// <summary>
34
        /// Gets this <see cref="SvgClipPath"/>'s region to be used as a clipping region.
35
        /// </summary>
36
37
        /// <returns>A new <see cref="Region"/> containing the <see cref="Region"/> to be used for clipping.</returns>
        public Region GetClipRegion(SvgVisualElement owner)
davescriven's avatar
davescriven committed
38
        {
39
            if (cachedClipPath == null || this._pathDirty)
40
            {
41
42
                cachedClipPath = new GraphicsPath();

davescriven's avatar
davescriven committed
43
                foreach (SvgElement element in this.Children)
44
                {
45
                    this.CombinePaths(cachedClipPath, element);
46
                }
davescriven's avatar
davescriven committed
47

48
                this._pathDirty = false;
davescriven's avatar
davescriven committed
49
50
            }

51
            return new Region(cachedClipPath);
davescriven's avatar
davescriven committed
52
53
        }

54
55
56
57
58
        /// <summary>
        /// 
        /// </summary>
        /// <param name="region"></param>
        /// <param name="element"></param>
59
        private void CombinePaths(GraphicsPath path, SvgElement element)
davescriven's avatar
davescriven committed
60
        {
61
            var graphicsElement = element as SvgVisualElement;
davescriven's avatar
davescriven committed
62

63
            if (graphicsElement != null && graphicsElement.Path != null)
64
            {
65
66
                path.FillMode = (graphicsElement.ClipRule == SvgClipRule.NonZero) ? FillMode.Winding : FillMode.Alternate;
                path.AddPath(graphicsElement.Path, false);
67
            }
davescriven's avatar
davescriven committed
68
69

            foreach (SvgElement child in element.Children)
70
            {
71
                this.CombinePaths(path, child);
72
            }
davescriven's avatar
davescriven committed
73
74
        }

75
76
77
78
79
80
        /// <summary>
        /// Called by the underlying <see cref="SvgElement"/> when an element has been added to the
        /// <see cref="Children"/> collection.
        /// </summary>
        /// <param name="child">The <see cref="SvgElement"/> that has been added.</param>
        /// <param name="index">An <see cref="int"/> representing the index where the element was added to the collection.</param>
81
        protected override void AddElement(SvgElement child, int index)
davescriven's avatar
davescriven committed
82
        {
83
            base.AddElement(child, index);
davescriven's avatar
davescriven committed
84
85
86
            this._pathDirty = true;
        }

87
88
89
90
91
        /// <summary>
        /// Called by the underlying <see cref="SvgElement"/> when an element has been removed from the
        /// <see cref="Children"/> collection.
        /// </summary>
        /// <param name="child">The <see cref="SvgElement"/> that has been removed.</param>
92
        protected override void RemoveElement(SvgElement child)
davescriven's avatar
davescriven committed
93
        {
94
            base.RemoveElement(child);
davescriven's avatar
davescriven committed
95
96
97
            this._pathDirty = true;
        }

98
99
100
101
        /// <summary>
        /// Renders the <see cref="SvgElement"/> and contents to the specified <see cref="SvgRenderer"/> object.
        /// </summary>
        /// <param name="renderer">The <see cref="SvgRenderer"/> object to render to.</param>
102
        protected override void Render(SvgRenderer renderer)
davescriven's avatar
davescriven committed
103
104
105
106
107
        {
            // Do nothing
        }
    }
}