[12762] | 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 | }
|
---|