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 | }
|
---|