[12762] | 1 | using System;
|
---|
| 2 | using System.Xml;
|
---|
| 3 | using System.Linq;
|
---|
| 4 | using System.Text;
|
---|
| 5 | using System.Collections.Generic;
|
---|
| 6 |
|
---|
| 7 | using System.Windows;
|
---|
| 8 | using System.Windows.Media;
|
---|
| 9 |
|
---|
| 10 | using SharpVectors.Dom.Svg;
|
---|
| 11 | using SharpVectors.Dom.Css;
|
---|
| 12 |
|
---|
| 13 | namespace SharpVectors.Renderers.Wpf
|
---|
| 14 | {
|
---|
| 15 | public sealed class WpfPatternFill : WpfFill
|
---|
| 16 | {
|
---|
| 17 | #region Private Fields
|
---|
| 18 |
|
---|
| 19 | private XmlElement oldParent;
|
---|
| 20 | private SvgPatternElement _patternElement;
|
---|
| 21 |
|
---|
| 22 | #endregion
|
---|
| 23 |
|
---|
| 24 | #region Constructors and Destructor
|
---|
| 25 |
|
---|
| 26 | public WpfPatternFill(SvgPatternElement patternElement)
|
---|
| 27 | {
|
---|
| 28 | _patternElement = patternElement;
|
---|
| 29 | }
|
---|
| 30 |
|
---|
| 31 | #endregion
|
---|
| 32 |
|
---|
| 33 | #region Public Methods
|
---|
| 34 |
|
---|
| 35 | public override Brush GetBrush(WpfDrawingContext context)
|
---|
| 36 | {
|
---|
| 37 | Rect bounds = new Rect(0, 0, 1, 1);
|
---|
| 38 | Drawing image = GetImage(context);
|
---|
| 39 | Rect destRect = GetDestRect(bounds);
|
---|
| 40 |
|
---|
| 41 | DrawingBrush tb = new DrawingBrush(image);
|
---|
| 42 | //tb.Viewbox = new Rect(0, 0, destRect.Width, destRect.Height);
|
---|
| 43 | //tb.Viewport = new Rect(0, 0, destRect.Width, destRect.Height);
|
---|
| 44 | tb.Viewbox = destRect;
|
---|
| 45 | tb.Viewport = destRect;
|
---|
| 46 | tb.ViewboxUnits = BrushMappingMode.Absolute;
|
---|
| 47 | tb.ViewportUnits = BrushMappingMode.Absolute;
|
---|
| 48 | tb.TileMode = TileMode.Tile;
|
---|
| 49 |
|
---|
| 50 | MatrixTransform transform = GetTransformMatrix(image.Bounds);
|
---|
| 51 | if (transform != null && !transform.Matrix.IsIdentity)
|
---|
| 52 | {
|
---|
| 53 | tb.Transform = transform;
|
---|
| 54 | }
|
---|
| 55 |
|
---|
| 56 | return tb;
|
---|
| 57 | }
|
---|
| 58 |
|
---|
| 59 | #endregion
|
---|
| 60 |
|
---|
| 61 | #region Private Methods
|
---|
| 62 |
|
---|
| 63 | private SvgSvgElement MoveIntoSvgElement()
|
---|
| 64 | {
|
---|
| 65 | SvgDocument doc = _patternElement.OwnerDocument;
|
---|
| 66 | SvgSvgElement svgElm = doc.CreateElement("", "svg", SvgDocument.SvgNamespace) as SvgSvgElement;
|
---|
| 67 |
|
---|
| 68 | XmlNodeList children = _patternElement.Children;
|
---|
| 69 | if (children.Count > 0)
|
---|
| 70 | {
|
---|
| 71 | oldParent = children[0].ParentNode as XmlElement;
|
---|
| 72 | }
|
---|
| 73 |
|
---|
| 74 | for (int i = 0; i < children.Count; i++)
|
---|
| 75 | {
|
---|
| 76 | svgElm.AppendChild(children[i]);
|
---|
| 77 | }
|
---|
| 78 |
|
---|
| 79 | if (_patternElement.HasAttribute("viewBox"))
|
---|
| 80 | {
|
---|
| 81 | svgElm.SetAttribute("viewBox", _patternElement.GetAttribute("viewBox"));
|
---|
| 82 | }
|
---|
| 83 | //svgElm.SetAttribute("x", "0");
|
---|
| 84 | //svgElm.SetAttribute("y", "0");
|
---|
| 85 | svgElm.SetAttribute("x", _patternElement.GetAttribute("x"));
|
---|
| 86 | svgElm.SetAttribute("y", _patternElement.GetAttribute("y"));
|
---|
| 87 | svgElm.SetAttribute("width", _patternElement.GetAttribute("width"));
|
---|
| 88 | svgElm.SetAttribute("height", _patternElement.GetAttribute("height"));
|
---|
| 89 |
|
---|
| 90 | if (_patternElement.PatternContentUnits.AnimVal.Equals(SvgUnitType.ObjectBoundingBox))
|
---|
| 91 | {
|
---|
| 92 | svgElm.SetAttribute("viewBox", "0 0 1 1");
|
---|
| 93 | }
|
---|
| 94 |
|
---|
| 95 | _patternElement.AppendChild(svgElm);
|
---|
| 96 |
|
---|
| 97 | return svgElm;
|
---|
| 98 | }
|
---|
| 99 |
|
---|
| 100 | private void MoveOutOfSvgElement(SvgSvgElement svgElm)
|
---|
| 101 | {
|
---|
| 102 | while (svgElm.ChildNodes.Count > 0)
|
---|
| 103 | {
|
---|
| 104 | oldParent.AppendChild(svgElm.ChildNodes[0]);
|
---|
| 105 | }
|
---|
| 106 |
|
---|
| 107 | _patternElement.RemoveChild(svgElm);
|
---|
| 108 | }
|
---|
| 109 |
|
---|
| 110 | private Drawing GetImage(WpfDrawingContext context)
|
---|
| 111 | {
|
---|
| 112 | WpfDrawingRenderer renderer = new WpfDrawingRenderer();
|
---|
| 113 | renderer.Window = _patternElement.OwnerDocument.Window as SvgWindow;
|
---|
| 114 |
|
---|
| 115 | WpfDrawingSettings settings = context.Settings.Clone();
|
---|
| 116 | settings.TextAsGeometry = true;
|
---|
| 117 | WpfDrawingContext patternContext = new WpfDrawingContext(true,
|
---|
| 118 | settings);
|
---|
| 119 |
|
---|
| 120 | patternContext.Initialize(null, context.FontFamilyVisitor, null);
|
---|
| 121 |
|
---|
| 122 | SvgSvgElement elm = MoveIntoSvgElement();
|
---|
| 123 |
|
---|
| 124 | renderer.Render((SvgElement)elm, patternContext);
|
---|
| 125 | Drawing img = renderer.Drawing;
|
---|
| 126 |
|
---|
| 127 | MoveOutOfSvgElement(elm);
|
---|
| 128 |
|
---|
| 129 | return img;
|
---|
| 130 | }
|
---|
| 131 |
|
---|
| 132 | private double CalcPatternUnit(SvgLength length, SvgLengthDirection dir, Rect bounds)
|
---|
| 133 | {
|
---|
| 134 | if (_patternElement.PatternUnits.AnimVal.Equals(SvgUnitType.UserSpaceOnUse))
|
---|
| 135 | {
|
---|
| 136 | return length.Value;
|
---|
| 137 | }
|
---|
| 138 | else
|
---|
| 139 | {
|
---|
| 140 | double calcValue = length.ValueInSpecifiedUnits;
|
---|
| 141 | if (dir == SvgLengthDirection.Horizontal)
|
---|
| 142 | {
|
---|
| 143 | calcValue *= bounds.Width;
|
---|
| 144 | }
|
---|
| 145 | else
|
---|
| 146 | {
|
---|
| 147 | calcValue *= bounds.Height;
|
---|
| 148 | }
|
---|
| 149 | if (length.UnitType == SvgLengthType.Percentage)
|
---|
| 150 | {
|
---|
| 151 | calcValue /= 100F;
|
---|
| 152 | }
|
---|
| 153 |
|
---|
| 154 | return calcValue;
|
---|
| 155 | }
|
---|
| 156 | }
|
---|
| 157 |
|
---|
| 158 | private Rect GetDestRect(Rect bounds)
|
---|
| 159 | {
|
---|
| 160 | Rect result = new Rect(0, 0, 0, 0);
|
---|
| 161 |
|
---|
| 162 | result.X = CalcPatternUnit(_patternElement.X.AnimVal as SvgLength,
|
---|
| 163 | SvgLengthDirection.Horizontal, bounds);
|
---|
| 164 | result.Y = CalcPatternUnit(_patternElement.Y.AnimVal as SvgLength,
|
---|
| 165 | SvgLengthDirection.Vertical, bounds);
|
---|
| 166 |
|
---|
| 167 | result.Width = CalcPatternUnit(_patternElement.Width.AnimVal as SvgLength,
|
---|
| 168 | SvgLengthDirection.Horizontal, bounds);
|
---|
| 169 | result.Height = CalcPatternUnit(_patternElement.Height.AnimVal as SvgLength,
|
---|
| 170 | SvgLengthDirection.Vertical, bounds);
|
---|
| 171 |
|
---|
| 172 | return result;
|
---|
| 173 | }
|
---|
| 174 |
|
---|
| 175 | private MatrixTransform GetTransformMatrix(Rect bounds)
|
---|
| 176 | {
|
---|
| 177 | SvgMatrix svgMatrix =
|
---|
| 178 | ((SvgTransformList)_patternElement.PatternTransform.AnimVal).TotalMatrix;
|
---|
| 179 |
|
---|
| 180 | MatrixTransform transformMatrix = new MatrixTransform(svgMatrix.A, svgMatrix.B, svgMatrix.C,
|
---|
| 181 | svgMatrix.D, svgMatrix.E, svgMatrix.F);
|
---|
| 182 |
|
---|
| 183 | double translateX = CalcPatternUnit(_patternElement.X.AnimVal as SvgLength,
|
---|
| 184 | SvgLengthDirection.Horizontal, bounds);
|
---|
| 185 | double translateY = CalcPatternUnit(_patternElement.Y.AnimVal as SvgLength,
|
---|
| 186 | SvgLengthDirection.Vertical, bounds);
|
---|
| 187 |
|
---|
| 188 | transformMatrix.Matrix.TranslatePrepend(translateX, translateY);
|
---|
| 189 |
|
---|
| 190 | return transformMatrix;
|
---|
| 191 | }
|
---|
| 192 |
|
---|
| 193 | #endregion
|
---|
| 194 | }
|
---|
| 195 | }
|
---|