-
Bigous authoredbd93be68
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Drawing.Drawing2D;
using Svg.Transforms;
namespace Svg
{
/// <summary>
/// Defines a path that can be used by other <see cref="ISvgClipable"/> elements.
/// </summary>
[SvgElement("clipPath")]
public sealed class SvgClipPath : SvgElement
{
private bool _pathDirty = true;
/// <summary>
/// Specifies the coordinate system for the clipping path.
/// </summary>
[SvgAttribute("clipPathUnits")]
public SvgCoordinateUnits ClipPathUnits { get; set; }
/// <summary>
/// Initializes a new instance of the <see cref="SvgClipPath"/> class.
/// </summary>
public SvgClipPath()
{
this.ClipPathUnits = SvgCoordinateUnits.ObjectBoundingBox;
}
private GraphicsPath cachedClipPath = null;
/// <summary>
/// Gets this <see cref="SvgClipPath"/>'s region to be used as a clipping region.
/// </summary>
/// <returns>A new <see cref="Region"/> containing the <see cref="Region"/> to be used for clipping.</returns>
public Region GetClipRegion(SvgVisualElement owner)
{
if (cachedClipPath == null || this._pathDirty)
{
cachedClipPath = new GraphicsPath();
foreach (SvgElement element in this.Children)
{
this.CombinePaths(cachedClipPath, element);
}
this._pathDirty = false;
}
return new Region(cachedClipPath);
}
/// <summary>
///
/// </summary>
/// <param name="region"></param>
/// <param name="element"></param>
private void CombinePaths(GraphicsPath path, SvgElement element)
{
var graphicsElement = element as SvgVisualElement;
if (graphicsElement != null && graphicsElement.Path != null)
{
path.FillMode = (graphicsElement.ClipRule == SvgClipRule.NonZero) ? FillMode.Winding : FillMode.Alternate;
GraphicsPath childPath = graphicsElement.Path;
if (graphicsElement.Transforms != null)
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
{
foreach (SvgTransform transform in graphicsElement.Transforms)
{
childPath.Transform(transform.Matrix);
}
}
path.AddPath(childPath, false);
}
foreach (SvgElement child in element.Children)
{
this.CombinePaths(path, child);
}
}
/// <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>
protected override void AddElement(SvgElement child, int index)
{
base.AddElement(child, index);
this._pathDirty = true;
}
/// <summary>
/// Called by the underlying <see cref="SvgElement"/> when an element has been removed from the
/// <see cref="SvgElement.Children"/> collection.
/// </summary>
/// <param name="child">The <see cref="SvgElement"/> that has been removed.</param>
protected override void RemoveElement(SvgElement child)
{
base.RemoveElement(child);
this._pathDirty = true;
}
/// <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>
protected override void Render(SvgRenderer renderer)
{
// Do nothing
}
public override SvgElement DeepCopy()
{
return DeepCopy<SvgClipPath>();
}
public override SvgElement DeepCopy<T>()
{
var newObj = base.DeepCopy<T>() as SvgClipPath;
newObj.ClipPathUnits = this.ClipPathUnits;
return newObj;
}
}
}