1 | using System;
|
---|
2 | using System.IO;
|
---|
3 | using System.Xml;
|
---|
4 | using System.Drawing;
|
---|
5 | using System.Drawing.Imaging;
|
---|
6 | using System.Drawing.Drawing2D;
|
---|
7 |
|
---|
8 | using SharpVectors.Dom.Svg;
|
---|
9 | using SharpVectors.Dom.Css;
|
---|
10 |
|
---|
11 | namespace SharpVectors.Renderers.Gdi
|
---|
12 | {
|
---|
13 | public sealed class GdiPatternFill : GdiFill
|
---|
14 | {
|
---|
15 | #region Private Fields
|
---|
16 |
|
---|
17 | private XmlElement oldParent;
|
---|
18 | private SvgPatternElement _patternElement;
|
---|
19 |
|
---|
20 | #endregion
|
---|
21 |
|
---|
22 | #region Constructors and Destructor
|
---|
23 |
|
---|
24 | public GdiPatternFill(SvgPatternElement patternElement)
|
---|
25 | {
|
---|
26 | _patternElement = patternElement;
|
---|
27 | }
|
---|
28 |
|
---|
29 | #endregion
|
---|
30 |
|
---|
31 | #region Public Methods
|
---|
32 |
|
---|
33 | public override Brush GetBrush(RectangleF bounds)
|
---|
34 | {
|
---|
35 | Image image = GetImage(bounds);
|
---|
36 | RectangleF destRect = GetDestRect(bounds);
|
---|
37 |
|
---|
38 | TextureBrush tb = new TextureBrush(image, destRect);
|
---|
39 | tb.Transform = GetTransformMatrix(bounds);
|
---|
40 | return tb;
|
---|
41 | }
|
---|
42 |
|
---|
43 | #endregion
|
---|
44 |
|
---|
45 | #region Private Methods
|
---|
46 |
|
---|
47 | private SvgSvgElement MoveIntoSvgElement()
|
---|
48 | {
|
---|
49 | SvgDocument doc = _patternElement.OwnerDocument;
|
---|
50 | SvgSvgElement svgElm = doc.CreateElement("", "svg", SvgDocument.SvgNamespace) as SvgSvgElement;
|
---|
51 |
|
---|
52 | XmlNodeList children = _patternElement.Children;
|
---|
53 | if (children.Count > 0)
|
---|
54 | {
|
---|
55 | oldParent = children[0].ParentNode as XmlElement;
|
---|
56 | }
|
---|
57 |
|
---|
58 | for (int i = 0; i<children.Count; i++)
|
---|
59 | {
|
---|
60 | svgElm.AppendChild(children[i]);
|
---|
61 | }
|
---|
62 |
|
---|
63 | if (_patternElement.HasAttribute("viewBox"))
|
---|
64 | {
|
---|
65 | svgElm.SetAttribute("viewBox", _patternElement.GetAttribute("viewBox"));
|
---|
66 | }
|
---|
67 | svgElm.SetAttribute("x", "0");
|
---|
68 | svgElm.SetAttribute("y", "0");
|
---|
69 | svgElm.SetAttribute("width", _patternElement.GetAttribute("width"));
|
---|
70 | svgElm.SetAttribute("height", _patternElement.GetAttribute("height"));
|
---|
71 |
|
---|
72 | if (_patternElement.PatternContentUnits.AnimVal.Equals(SvgUnitType.ObjectBoundingBox))
|
---|
73 | {
|
---|
74 | svgElm.SetAttribute("viewBox", "0 0 1 1");
|
---|
75 | }
|
---|
76 |
|
---|
77 | _patternElement.AppendChild(svgElm);
|
---|
78 |
|
---|
79 | return svgElm;
|
---|
80 | }
|
---|
81 |
|
---|
82 | private void MoveOutOfSvgElement(SvgSvgElement svgElm)
|
---|
83 | {
|
---|
84 | while (svgElm.ChildNodes.Count > 0)
|
---|
85 | {
|
---|
86 | oldParent.AppendChild(svgElm.ChildNodes[0]);
|
---|
87 | }
|
---|
88 |
|
---|
89 | _patternElement.RemoveChild(svgElm);
|
---|
90 | }
|
---|
91 |
|
---|
92 | private Image GetImage(RectangleF bounds)
|
---|
93 | {
|
---|
94 | GdiGraphicsRenderer renderer = new GdiGraphicsRenderer();
|
---|
95 | renderer.Window = _patternElement.OwnerDocument.Window as SvgWindow;
|
---|
96 |
|
---|
97 | SvgSvgElement elm = MoveIntoSvgElement();
|
---|
98 |
|
---|
99 | renderer.Render(elm as SvgElement);
|
---|
100 | Image img = renderer.RasterImage;
|
---|
101 |
|
---|
102 | MoveOutOfSvgElement(elm);
|
---|
103 |
|
---|
104 | return img;
|
---|
105 | }
|
---|
106 |
|
---|
107 |
|
---|
108 | private float CalcPatternUnit(SvgLength length, SvgLengthDirection dir, RectangleF bounds)
|
---|
109 | {
|
---|
110 | if (_patternElement.PatternUnits.AnimVal.Equals(SvgUnitType.UserSpaceOnUse))
|
---|
111 | {
|
---|
112 | return (float)length.Value;
|
---|
113 | }
|
---|
114 | else
|
---|
115 | {
|
---|
116 | float calcValue = (float)length.ValueInSpecifiedUnits;
|
---|
117 | if (dir == SvgLengthDirection.Horizontal)
|
---|
118 | {
|
---|
119 | calcValue *= bounds.Width;
|
---|
120 | }
|
---|
121 | else
|
---|
122 | {
|
---|
123 | calcValue *= bounds.Height;
|
---|
124 | }
|
---|
125 | if (length.UnitType == SvgLengthType.Percentage)
|
---|
126 | {
|
---|
127 | calcValue /= 100F;
|
---|
128 | }
|
---|
129 |
|
---|
130 | return calcValue;
|
---|
131 | }
|
---|
132 | }
|
---|
133 |
|
---|
134 | private RectangleF GetDestRect(RectangleF bounds)
|
---|
135 | {
|
---|
136 | RectangleF result = new RectangleF(0, 0, 0, 0);
|
---|
137 | result.Width = CalcPatternUnit(_patternElement.Width.AnimVal as SvgLength,
|
---|
138 | SvgLengthDirection.Horizontal, bounds);
|
---|
139 | result.Height = CalcPatternUnit(_patternElement.Height.AnimVal as SvgLength,
|
---|
140 | SvgLengthDirection.Vertical, bounds);
|
---|
141 |
|
---|
142 | return result;
|
---|
143 | }
|
---|
144 |
|
---|
145 | private Matrix GetTransformMatrix(RectangleF bounds)
|
---|
146 | {
|
---|
147 | SvgMatrix svgMatrix = ((SvgTransformList)_patternElement.PatternTransform.AnimVal).TotalMatrix;
|
---|
148 |
|
---|
149 | Matrix transformMatrix = new Matrix((float)svgMatrix.A, (float)svgMatrix.B, (float)svgMatrix.C,
|
---|
150 | (float)svgMatrix.D, (float)svgMatrix.E, (float)svgMatrix.F);
|
---|
151 |
|
---|
152 | float translateX = CalcPatternUnit(_patternElement.X.AnimVal as SvgLength,
|
---|
153 | SvgLengthDirection.Horizontal, bounds);
|
---|
154 | float translateY = CalcPatternUnit(_patternElement.Y.AnimVal as SvgLength,
|
---|
155 | SvgLengthDirection.Vertical, bounds);
|
---|
156 |
|
---|
157 | transformMatrix.Translate(translateX, translateY, MatrixOrder.Prepend);
|
---|
158 |
|
---|
159 | return transformMatrix;
|
---|
160 | }
|
---|
161 |
|
---|
162 | #endregion
|
---|
163 | }
|
---|
164 | }
|
---|