[12762] | 1 | using System;
|
---|
| 2 | using System.Drawing;
|
---|
| 3 | using System.Drawing.Drawing2D;
|
---|
| 4 |
|
---|
| 5 | using SharpVectors.Dom.Svg;
|
---|
| 6 | using SharpVectors.Dom.Css;
|
---|
| 7 |
|
---|
| 8 | namespace SharpVectors.Renderers.Gdi
|
---|
| 9 | {
|
---|
| 10 | public sealed class GdiSvgPaint : SvgPaint
|
---|
| 11 | {
|
---|
| 12 | #region Private Fields
|
---|
| 13 |
|
---|
| 14 | private GdiFill _paintFill;
|
---|
| 15 | private SvgStyleableElement _element;
|
---|
| 16 |
|
---|
| 17 | #endregion
|
---|
| 18 |
|
---|
| 19 | #region Constructors and Destructor
|
---|
| 20 |
|
---|
| 21 | public GdiSvgPaint(SvgStyleableElement elm, string propName)
|
---|
| 22 | : base(elm.GetComputedStyle("").GetPropertyValue(propName))
|
---|
| 23 | {
|
---|
| 24 | _element = elm;
|
---|
| 25 | }
|
---|
| 26 |
|
---|
| 27 | #endregion
|
---|
| 28 |
|
---|
| 29 | #region Public Properties
|
---|
| 30 |
|
---|
| 31 | public GdiFill PaintFill
|
---|
| 32 | {
|
---|
| 33 | get
|
---|
| 34 | {
|
---|
| 35 | return _paintFill;
|
---|
| 36 | }
|
---|
| 37 | }
|
---|
| 38 |
|
---|
| 39 | #endregion
|
---|
| 40 |
|
---|
| 41 | #region Public Methods
|
---|
| 42 |
|
---|
| 43 | public Brush GetBrush(GraphicsPath gp)
|
---|
| 44 | {
|
---|
| 45 | return GetBrush(gp, "fill");
|
---|
| 46 | }
|
---|
| 47 |
|
---|
| 48 | public Pen GetPen(GraphicsPath gp)
|
---|
| 49 | {
|
---|
| 50 | float strokeWidth = GetStrokeWidth();
|
---|
| 51 | if (strokeWidth == 0) return null;
|
---|
| 52 |
|
---|
| 53 | GdiSvgPaint stroke;
|
---|
| 54 | if (PaintType == SvgPaintType.None)
|
---|
| 55 | {
|
---|
| 56 | return null;
|
---|
| 57 | }
|
---|
| 58 | else if (PaintType == SvgPaintType.CurrentColor)
|
---|
| 59 | {
|
---|
| 60 | stroke = new GdiSvgPaint(_element, "color");
|
---|
| 61 | }
|
---|
| 62 | else
|
---|
| 63 | {
|
---|
| 64 | stroke = this;
|
---|
| 65 | }
|
---|
| 66 |
|
---|
| 67 | Pen pen = new Pen(stroke.GetBrush(gp, "stroke"), strokeWidth);
|
---|
| 68 |
|
---|
| 69 | pen.StartCap = pen.EndCap = GetLineCap();
|
---|
| 70 | pen.LineJoin = GetLineJoin();
|
---|
| 71 | pen.MiterLimit = GetMiterLimit();
|
---|
| 72 |
|
---|
| 73 | float[] fDashArray = GetDashArray(strokeWidth);
|
---|
| 74 | if (fDashArray != null)
|
---|
| 75 | {
|
---|
| 76 | // Do not draw if dash array had a zero value in it
|
---|
| 77 |
|
---|
| 78 | for (int i = 0; i < fDashArray.Length; i++)
|
---|
| 79 | {
|
---|
| 80 | if (fDashArray[i] == 0)
|
---|
| 81 | return null;
|
---|
| 82 | }
|
---|
| 83 |
|
---|
| 84 | pen.DashPattern = fDashArray;
|
---|
| 85 | }
|
---|
| 86 |
|
---|
| 87 | pen.DashOffset = GetDashOffset(strokeWidth);
|
---|
| 88 |
|
---|
| 89 | return pen;
|
---|
| 90 | }
|
---|
| 91 |
|
---|
| 92 | #endregion
|
---|
| 93 |
|
---|
| 94 | #region Private Methods
|
---|
| 95 |
|
---|
| 96 | private int GetOpacity(string fillOrStroke)
|
---|
| 97 | {
|
---|
| 98 | double alpha = 255;
|
---|
| 99 | string opacity;
|
---|
| 100 |
|
---|
| 101 | opacity = _element.GetPropertyValue(fillOrStroke + "-opacity");
|
---|
| 102 | if (opacity.Length > 0) alpha *= SvgNumber.ParseNumber(opacity);
|
---|
| 103 |
|
---|
| 104 | opacity = _element.GetPropertyValue("opacity");
|
---|
| 105 | if (opacity.Length > 0) alpha *= SvgNumber.ParseNumber(opacity);
|
---|
| 106 |
|
---|
| 107 | alpha = Math.Min(alpha, 255);
|
---|
| 108 | alpha = Math.Max(alpha, 0);
|
---|
| 109 |
|
---|
| 110 | return Convert.ToInt32(alpha);
|
---|
| 111 | }
|
---|
| 112 |
|
---|
| 113 | private LineCap GetLineCap()
|
---|
| 114 | {
|
---|
| 115 | switch (_element.GetPropertyValue("stroke-linecap"))
|
---|
| 116 | {
|
---|
| 117 | case "round":
|
---|
| 118 | return LineCap.Round;
|
---|
| 119 | case "square":
|
---|
| 120 | return LineCap.Square;
|
---|
| 121 | default:
|
---|
| 122 | return LineCap.Flat;
|
---|
| 123 | }
|
---|
| 124 | }
|
---|
| 125 |
|
---|
| 126 | private LineJoin GetLineJoin()
|
---|
| 127 | {
|
---|
| 128 | switch (_element.GetPropertyValue("stroke-linejoin"))
|
---|
| 129 | {
|
---|
| 130 | case "round":
|
---|
| 131 | return LineJoin.Round;
|
---|
| 132 | case "bevel":
|
---|
| 133 | return LineJoin.Bevel;
|
---|
| 134 | default:
|
---|
| 135 | return LineJoin.Miter;
|
---|
| 136 | }
|
---|
| 137 | }
|
---|
| 138 |
|
---|
| 139 | private float GetStrokeWidth()
|
---|
| 140 | {
|
---|
| 141 | string strokeWidth = _element.GetPropertyValue("stroke-width");
|
---|
| 142 | if (strokeWidth.Length == 0) strokeWidth = "1px";
|
---|
| 143 |
|
---|
| 144 | SvgLength strokeWidthLength = new SvgLength(_element, "stroke-width", SvgLengthDirection.Viewport, strokeWidth);
|
---|
| 145 | return (float)strokeWidthLength.Value;
|
---|
| 146 | }
|
---|
| 147 |
|
---|
| 148 | private float GetMiterLimit()
|
---|
| 149 | {
|
---|
| 150 | string miterLimitStr = _element.GetPropertyValue("stroke-miterlimit");
|
---|
| 151 | if (miterLimitStr.Length == 0) miterLimitStr = "4";
|
---|
| 152 |
|
---|
| 153 | float miterLimit = (float)SvgNumber.ParseNumber(miterLimitStr);
|
---|
| 154 | if (miterLimit < 1) throw new SvgException(SvgExceptionType.SvgInvalidValueErr, "stroke-miterlimit can not be less then 1");
|
---|
| 155 |
|
---|
| 156 | return miterLimit;
|
---|
| 157 | }
|
---|
| 158 |
|
---|
| 159 | private float[] GetDashArray(float strokeWidth)
|
---|
| 160 | {
|
---|
| 161 | string dashArray = _element.GetPropertyValue("stroke-dasharray");
|
---|
| 162 |
|
---|
| 163 | if (dashArray.Length == 0 || dashArray == "none")
|
---|
| 164 | {
|
---|
| 165 | return null;
|
---|
| 166 | }
|
---|
| 167 | else
|
---|
| 168 | {
|
---|
| 169 | SvgNumberList list = new SvgNumberList(dashArray);
|
---|
| 170 |
|
---|
| 171 | uint len = list.NumberOfItems;
|
---|
| 172 | float[] fDashArray = new float[len];
|
---|
| 173 |
|
---|
| 174 | for (uint i = 0; i < len; i++)
|
---|
| 175 | {
|
---|
| 176 | //divide by strokeWidth to take care of the difference between Svg and GDI+
|
---|
| 177 | fDashArray[i] = (float)(list.GetItem(i).Value / strokeWidth);
|
---|
| 178 | }
|
---|
| 179 |
|
---|
| 180 | if (len % 2 == 1)
|
---|
| 181 | {
|
---|
| 182 | //odd number of values, duplicate
|
---|
| 183 | float[] tmpArray = new float[len * 2];
|
---|
| 184 | fDashArray.CopyTo(tmpArray, 0);
|
---|
| 185 | fDashArray.CopyTo(tmpArray, (int)len);
|
---|
| 186 |
|
---|
| 187 | fDashArray = tmpArray;
|
---|
| 188 | }
|
---|
| 189 |
|
---|
| 190 | return fDashArray;
|
---|
| 191 | }
|
---|
| 192 | }
|
---|
| 193 |
|
---|
| 194 | private float GetDashOffset(float strokeWidth)
|
---|
| 195 | {
|
---|
| 196 | string dashOffset = _element.GetPropertyValue("stroke-dashoffset");
|
---|
| 197 | if (dashOffset.Length > 0)
|
---|
| 198 | {
|
---|
| 199 | //divide by strokeWidth to take care of the difference between Svg and GDI+
|
---|
| 200 | SvgLength dashOffsetLength = new SvgLength(_element, "stroke-dashoffset", SvgLengthDirection.Viewport, dashOffset);
|
---|
| 201 | return (float)dashOffsetLength.Value;
|
---|
| 202 | }
|
---|
| 203 | else
|
---|
| 204 | {
|
---|
| 205 | return 0;
|
---|
| 206 | }
|
---|
| 207 | }
|
---|
| 208 |
|
---|
| 209 | private GdiFill GetPaintFill(string uri)
|
---|
| 210 | {
|
---|
| 211 | string absoluteUri = _element.ResolveUri(uri);
|
---|
| 212 |
|
---|
| 213 | return GdiFill.CreateFill(_element.OwnerDocument, absoluteUri);
|
---|
| 214 | }
|
---|
| 215 |
|
---|
| 216 | private Brush GetBrush(GraphicsPath gp, string propPrefix)
|
---|
| 217 | {
|
---|
| 218 | SvgPaint painter;
|
---|
| 219 | SvgPaintType curPaintType = this.PaintType;
|
---|
| 220 | if (curPaintType == SvgPaintType.None)
|
---|
| 221 | {
|
---|
| 222 | return null;
|
---|
| 223 | }
|
---|
| 224 | else if (curPaintType == SvgPaintType.CurrentColor)
|
---|
| 225 | {
|
---|
| 226 | painter = new GdiSvgPaint(_element, "color");
|
---|
| 227 | }
|
---|
| 228 | else
|
---|
| 229 | {
|
---|
| 230 | painter = this;
|
---|
| 231 | }
|
---|
| 232 |
|
---|
| 233 | SvgPaintType paintType = painter.PaintType;
|
---|
| 234 | if (paintType == SvgPaintType.Uri || paintType == SvgPaintType.UriCurrentColor ||
|
---|
| 235 | paintType == SvgPaintType.UriNone || paintType == SvgPaintType.UriRgbColor ||
|
---|
| 236 | paintType == SvgPaintType.UriRgbColorIccColor)
|
---|
| 237 | {
|
---|
| 238 | _paintFill = GetPaintFill(painter.Uri);
|
---|
| 239 | if (_paintFill != null)
|
---|
| 240 | {
|
---|
| 241 | Brush br = _paintFill.GetBrush(gp.GetBounds());
|
---|
| 242 |
|
---|
| 243 | LinearGradientBrush lgb = br as LinearGradientBrush;
|
---|
| 244 | if (lgb != null)
|
---|
| 245 | {
|
---|
| 246 | int opacityl = GetOpacity(propPrefix);
|
---|
| 247 | for (int i = 0; i < lgb.InterpolationColors.Colors.Length; i++)
|
---|
| 248 | {
|
---|
| 249 | lgb.InterpolationColors.Colors[i] =
|
---|
| 250 | Color.FromArgb(opacityl, lgb.InterpolationColors.Colors[i]);
|
---|
| 251 | }
|
---|
| 252 | for (int i = 0; i < lgb.LinearColors.Length; i++)
|
---|
| 253 | {
|
---|
| 254 | lgb.LinearColors[i] = Color.FromArgb(opacityl, lgb.LinearColors[i]);
|
---|
| 255 | }
|
---|
| 256 |
|
---|
| 257 | return br;
|
---|
| 258 | }
|
---|
| 259 |
|
---|
| 260 | PathGradientBrush pgb = br as PathGradientBrush;
|
---|
| 261 | if (pgb != null)
|
---|
| 262 | {
|
---|
| 263 | int opacityl = GetOpacity(propPrefix);
|
---|
| 264 | for (int i = 0; i < pgb.InterpolationColors.Colors.Length; i++)
|
---|
| 265 | {
|
---|
| 266 | pgb.InterpolationColors.Colors[i] =
|
---|
| 267 | Color.FromArgb(opacityl, pgb.InterpolationColors.Colors[i]);
|
---|
| 268 | }
|
---|
| 269 | for (int i = 0; i < pgb.SurroundColors.Length; i++)
|
---|
| 270 | {
|
---|
| 271 | pgb.SurroundColors[i] = Color.FromArgb(opacityl, pgb.SurroundColors[i]);
|
---|
| 272 | }
|
---|
| 273 |
|
---|
| 274 | return br;
|
---|
| 275 | }
|
---|
| 276 | }
|
---|
| 277 | else
|
---|
| 278 | {
|
---|
| 279 | if (curPaintType == SvgPaintType.UriNone ||
|
---|
| 280 | curPaintType == SvgPaintType.Uri)
|
---|
| 281 | {
|
---|
| 282 | return null;
|
---|
| 283 | }
|
---|
| 284 | else if (curPaintType == SvgPaintType.UriCurrentColor)
|
---|
| 285 | {
|
---|
| 286 | painter = new GdiSvgPaint(_element, "color");
|
---|
| 287 | }
|
---|
| 288 | else
|
---|
| 289 | {
|
---|
| 290 | painter = this;
|
---|
| 291 | }
|
---|
| 292 | }
|
---|
| 293 | }
|
---|
| 294 |
|
---|
| 295 | if (painter == null || painter.RgbColor == null)
|
---|
| 296 | {
|
---|
| 297 | return null;
|
---|
| 298 | }
|
---|
| 299 |
|
---|
| 300 | SolidBrush brush = new SolidBrush(GdiConverter.ToColor(painter.RgbColor));
|
---|
| 301 | int opacity = GetOpacity(propPrefix);
|
---|
| 302 | brush.Color = Color.FromArgb(opacity, brush.Color);
|
---|
| 303 | return brush;
|
---|
| 304 | }
|
---|
| 305 |
|
---|
| 306 | #endregion
|
---|
| 307 | }
|
---|
| 308 | }
|
---|