using System; using System.Xml; using System.Linq; using System.Text; using System.Collections.Generic; using System.Windows; using System.Windows.Media; using SharpVectors.Dom.Svg; using SharpVectors.Dom.Css; namespace SharpVectors.Renderers.Wpf { public sealed class WpfPatternFill : WpfFill { #region Private Fields private XmlElement oldParent; private SvgPatternElement _patternElement; #endregion #region Constructors and Destructor public WpfPatternFill(SvgPatternElement patternElement) { _patternElement = patternElement; } #endregion #region Public Methods public override Brush GetBrush(WpfDrawingContext context) { Rect bounds = new Rect(0, 0, 1, 1); Drawing image = GetImage(context); Rect destRect = GetDestRect(bounds); DrawingBrush tb = new DrawingBrush(image); //tb.Viewbox = new Rect(0, 0, destRect.Width, destRect.Height); //tb.Viewport = new Rect(0, 0, destRect.Width, destRect.Height); tb.Viewbox = destRect; tb.Viewport = destRect; tb.ViewboxUnits = BrushMappingMode.Absolute; tb.ViewportUnits = BrushMappingMode.Absolute; tb.TileMode = TileMode.Tile; MatrixTransform transform = GetTransformMatrix(image.Bounds); if (transform != null && !transform.Matrix.IsIdentity) { tb.Transform = transform; } return tb; } #endregion #region Private Methods private SvgSvgElement MoveIntoSvgElement() { SvgDocument doc = _patternElement.OwnerDocument; SvgSvgElement svgElm = doc.CreateElement("", "svg", SvgDocument.SvgNamespace) as SvgSvgElement; XmlNodeList children = _patternElement.Children; if (children.Count > 0) { oldParent = children[0].ParentNode as XmlElement; } for (int i = 0; i < children.Count; i++) { svgElm.AppendChild(children[i]); } if (_patternElement.HasAttribute("viewBox")) { svgElm.SetAttribute("viewBox", _patternElement.GetAttribute("viewBox")); } //svgElm.SetAttribute("x", "0"); //svgElm.SetAttribute("y", "0"); svgElm.SetAttribute("x", _patternElement.GetAttribute("x")); svgElm.SetAttribute("y", _patternElement.GetAttribute("y")); svgElm.SetAttribute("width", _patternElement.GetAttribute("width")); svgElm.SetAttribute("height", _patternElement.GetAttribute("height")); if (_patternElement.PatternContentUnits.AnimVal.Equals(SvgUnitType.ObjectBoundingBox)) { svgElm.SetAttribute("viewBox", "0 0 1 1"); } _patternElement.AppendChild(svgElm); return svgElm; } private void MoveOutOfSvgElement(SvgSvgElement svgElm) { while (svgElm.ChildNodes.Count > 0) { oldParent.AppendChild(svgElm.ChildNodes[0]); } _patternElement.RemoveChild(svgElm); } private Drawing GetImage(WpfDrawingContext context) { WpfDrawingRenderer renderer = new WpfDrawingRenderer(); renderer.Window = _patternElement.OwnerDocument.Window as SvgWindow; WpfDrawingSettings settings = context.Settings.Clone(); settings.TextAsGeometry = true; WpfDrawingContext patternContext = new WpfDrawingContext(true, settings); patternContext.Initialize(null, context.FontFamilyVisitor, null); SvgSvgElement elm = MoveIntoSvgElement(); renderer.Render((SvgElement)elm, patternContext); Drawing img = renderer.Drawing; MoveOutOfSvgElement(elm); return img; } private double CalcPatternUnit(SvgLength length, SvgLengthDirection dir, Rect bounds) { if (_patternElement.PatternUnits.AnimVal.Equals(SvgUnitType.UserSpaceOnUse)) { return length.Value; } else { double calcValue = length.ValueInSpecifiedUnits; if (dir == SvgLengthDirection.Horizontal) { calcValue *= bounds.Width; } else { calcValue *= bounds.Height; } if (length.UnitType == SvgLengthType.Percentage) { calcValue /= 100F; } return calcValue; } } private Rect GetDestRect(Rect bounds) { Rect result = new Rect(0, 0, 0, 0); result.X = CalcPatternUnit(_patternElement.X.AnimVal as SvgLength, SvgLengthDirection.Horizontal, bounds); result.Y = CalcPatternUnit(_patternElement.Y.AnimVal as SvgLength, SvgLengthDirection.Vertical, bounds); result.Width = CalcPatternUnit(_patternElement.Width.AnimVal as SvgLength, SvgLengthDirection.Horizontal, bounds); result.Height = CalcPatternUnit(_patternElement.Height.AnimVal as SvgLength, SvgLengthDirection.Vertical, bounds); return result; } private MatrixTransform GetTransformMatrix(Rect bounds) { SvgMatrix svgMatrix = ((SvgTransformList)_patternElement.PatternTransform.AnimVal).TotalMatrix; MatrixTransform transformMatrix = new MatrixTransform(svgMatrix.A, svgMatrix.B, svgMatrix.C, svgMatrix.D, svgMatrix.E, svgMatrix.F); double translateX = CalcPatternUnit(_patternElement.X.AnimVal as SvgLength, SvgLengthDirection.Horizontal, bounds); double translateY = CalcPatternUnit(_patternElement.Y.AnimVal as SvgLength, SvgLengthDirection.Vertical, bounds); transformMatrix.Matrix.TranslatePrepend(translateX, translateY); return transformMatrix; } #endregion } }