using System; using System.Collections.Generic; using System.Text; using System.Drawing; using System.Drawing.Drawing2D; using Svg.Transforms; namespace Svg { /// /// Defines a path that can be used by other elements. /// [SvgElement("clipPath")] public sealed class SvgClipPath : SvgElement { private bool _pathDirty = true; /// /// Specifies the coordinate system for the clipping path. /// [SvgAttribute("clipPathUnits")] public SvgCoordinateUnits ClipPathUnits { get; set; } /// /// Initializes a new instance of the class. /// public SvgClipPath() { this.ClipPathUnits = SvgCoordinateUnits.Inherit; } private GraphicsPath cachedClipPath = null; /// /// Gets this 's region to be used as a clipping region. /// /// A new containing the to be used for clipping. 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; } var result = cachedClipPath; if (ClipPathUnits == SvgCoordinateUnits.ObjectBoundingBox) { result = (GraphicsPath)cachedClipPath.Clone(); using (var transform = new Matrix()) { var bounds = owner.Bounds; transform.Scale(bounds.Width, bounds.Height, MatrixOrder.Append); transform.Translate(bounds.Left, bounds.Top, MatrixOrder.Append); result.Transform(transform); } } return new Region(result); } /// /// /// /// /// private void CombinePaths(GraphicsPath path, SvgElement element) { var graphicsElement = element as SvgVisualElement; if (graphicsElement != null && graphicsElement.Path(null) != null) { path.FillMode = (graphicsElement.ClipRule == SvgClipRule.NonZero) ? FillMode.Winding : FillMode.Alternate; GraphicsPath childPath = graphicsElement.Path(null); if (graphicsElement.Transforms != null) { foreach (SvgTransform transform in graphicsElement.Transforms) { childPath.Transform(transform.Matrix); } } if (childPath.PointCount > 0) path.AddPath(childPath, false); } foreach (SvgElement child in element.Children) { this.CombinePaths(path, child); } } /// /// Called by the underlying when an element has been added to the /// collection. /// /// The that has been added. /// An representing the index where the element was added to the collection. protected override void AddElement(SvgElement child, int index) { base.AddElement(child, index); this._pathDirty = true; } /// /// Called by the underlying when an element has been removed from the /// collection. /// /// The that has been removed. protected override void RemoveElement(SvgElement child) { base.RemoveElement(child); this._pathDirty = true; } /// /// Renders the and contents to the specified object. /// /// The object to render to. protected override void Render(ISvgRenderer renderer) { // Do nothing } public override SvgElement DeepCopy() { return DeepCopy(); } public override SvgElement DeepCopy() { var newObj = base.DeepCopy() as SvgClipPath; newObj.ClipPathUnits = this.ClipPathUnits; return newObj; } } }