Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.Problems.GrammaticalOptimization/SharpVectorRenderingWpf/Wpf/WpfSvgPaint.cs @ 13777

Last change on this file since 13777 was 12762, checked in by aballeit, 9 years ago

#2283 GUI updates, Tree-chart, MCTS Version 2 (prune leaves)

File size: 12.0 KB
Line 
1using System;
2using System.Windows;
3using System.Windows.Media;
4
5using SharpVectors.Dom.Svg;
6using SharpVectors.Dom.Css;
7using SharpVectors.Renderers.Utils;
8
9namespace SharpVectors.Renderers.Wpf
10{
11    public sealed class WpfSvgPaint : SvgPaint
12    {
13        #region Private Fields
14
15        private string  _propertyName;
16        private WpfFill _paintFill;
17        private SvgStyleableElement _element;
18        private WpfDrawingContext _context;
19
20        #endregion
21
22        #region Constructors and Destructor
23
24        public WpfSvgPaint(WpfDrawingContext context, SvgStyleableElement elm, string propName)
25            : base(elm.GetComputedStyle("").GetPropertyValue(propName))
26        {
27            _propertyName = propName;
28            _element      = elm;
29            _context      = context;
30        }
31
32        #endregion
33
34        #region Public Properties
35
36        public WpfFill PaintServer
37        {
38            get
39            {
40                return _paintFill;
41            }
42        }
43
44        #endregion
45
46        #region Public Methods
47
48        public Brush GetBrush()
49        {
50            return GetBrush("fill", true);
51        }
52
53        public Brush GetBrush(bool setOpacity)
54        {
55            return GetBrush("fill", setOpacity);
56        }
57
58        public Pen GetPen()
59        {
60            double strokeWidth = GetStrokeWidth();
61            if (strokeWidth == 0)
62                return null;
63
64            WpfSvgPaint stroke;
65            if (PaintType == SvgPaintType.None)
66            {
67                return null;
68            }
69            else if (PaintType == SvgPaintType.CurrentColor)
70            {
71                stroke = new WpfSvgPaint(_context, _element, "color");
72            }
73            else
74            {
75                stroke = this;
76            }
77
78            Pen pen = new Pen(stroke.GetBrush("stroke", true), strokeWidth);
79
80            pen.StartLineCap = pen.EndLineCap = GetLineCap();
81            pen.LineJoin     = GetLineJoin();
82            double miterLimit = GetMiterLimit(strokeWidth);
83            if (miterLimit > 0)
84            {
85                pen.MiterLimit = miterLimit;
86            }
87
88            //pen.MiterLimit = 1.0f;
89
90            DoubleCollection dashArray = GetDashArray(strokeWidth);
91            if (dashArray != null && dashArray.Count != 0)
92            {
93                bool isValidDashes = true;
94                //Do not draw if dash array had a zero value in it
95                for (int i = 0; i < dashArray.Count; i++)
96                {
97                    if (dashArray[i] == 0)
98                    {
99                        isValidDashes = false;
100                    }
101                }
102
103                if (isValidDashes)
104                {   
105                    DashStyle dashStyle = new DashStyle(dashArray, GetDashOffset(strokeWidth));
106
107                    pen.DashStyle = dashStyle;
108                    // This is the one that works well for the XAML, the default is not Flat as
109                    // stated in the documentations...
110                    pen.DashCap   = PenLineCap.Flat;
111                }
112            }
113
114            return pen;
115        }
116
117        #endregion
118
119        #region Private Methods
120
121        private double GetOpacity(string fillOrStroke)
122        {
123            double opacityValue = 1;
124
125            string opacity = _element.GetPropertyValue(fillOrStroke + "-opacity");
126            if (opacity != null && opacity.Length > 0)
127            {
128                opacityValue *= SvgNumber.ParseNumber(opacity);
129            }
130
131            opacity = _element.GetPropertyValue("opacity");
132            if (opacity != null && opacity.Length > 0)
133            {
134                opacityValue *= SvgNumber.ParseNumber(opacity);
135            }
136
137            opacityValue = Math.Min(opacityValue, 1);
138            opacityValue = Math.Max(opacityValue, 0);
139
140            return opacityValue;
141        }
142
143        private PenLineCap GetLineCap()
144        {
145            switch (_element.GetPropertyValue("stroke-linecap"))
146            {
147                case "round":
148                    return PenLineCap.Round;
149                case "square":
150                    return PenLineCap.Square;
151                case "butt":
152                    return PenLineCap.Flat;
153               case "triangle":
154                    return PenLineCap.Triangle;
155                default:
156                    return PenLineCap.Flat;
157            }
158        }
159
160        private PenLineJoin GetLineJoin()
161        {
162            switch (_element.GetPropertyValue("stroke-linejoin"))
163            {
164                case "round":
165                    return PenLineJoin.Round;
166                case "bevel":
167                    return PenLineJoin.Bevel;
168                default:
169                    return PenLineJoin.Miter;
170            }
171        }
172
173        private double GetStrokeWidth()
174        {
175            string strokeWidth = _element.GetPropertyValue("stroke-width");
176            if (strokeWidth.Length == 0) strokeWidth = "1px";
177
178            SvgLength strokeWidthLength = new SvgLength(_element, "stroke-width",
179                SvgLengthDirection.Viewport, strokeWidth);
180
181            return strokeWidthLength.Value;
182        }
183
184        private double GetMiterLimit(double strokeWidth)
185        {
186            // Use this to prevent the default value of "4" being used...
187            string miterLimitAttr = _element.GetAttribute("stroke-miterlimit");
188            if (String.IsNullOrEmpty(miterLimitAttr))
189            {
190                string strokeLinecap = _element.GetAttribute("stroke-linecap");
191                if (String.Equals(strokeLinecap, "round", StringComparison.OrdinalIgnoreCase))
192                {
193                    return 1.0d;
194                }             
195                return -1.0d;
196            }                 
197
198            string miterLimitStr = _element.GetPropertyValue("stroke-miterlimit");
199            if (String.IsNullOrEmpty(miterLimitStr) || (float)(strokeWidth) <= 0)
200            {
201                return -1.0d;
202            }
203
204            double miterLimit = SvgNumber.ParseNumber(miterLimitStr);
205            if (miterLimit < 1)
206                throw new SvgException(SvgExceptionType.SvgInvalidValueErr,
207                    "stroke-miterlimit can not be less then 1");
208
209            //if (miterLimit < 1.0d)
210            //{
211            //    return -1.0d;
212            //}
213
214            double ratioLimit = miterLimit / strokeWidth;
215            if (ratioLimit >= 1.8d)
216            {
217                return miterLimit;
218            }
219            else
220            {
221                return 1.0d;
222            }
223        }
224
225        private DoubleCollection GetDashArray(double strokeWidth)
226        {
227            string dashArrayText = _element.GetPropertyValue("stroke-dasharray");
228            if (String.IsNullOrEmpty(dashArrayText))
229            {
230                return null;
231            }
232
233            if (dashArrayText == "none")
234            {
235                return null;
236            }
237            else
238            {
239                SvgNumberList list = new SvgNumberList(dashArrayText);
240
241                uint len = list.NumberOfItems;
242                //float[] fDashArray = new float[len];
243                DoubleCollection dashArray = new DoubleCollection((int)len);
244
245                for (uint i = 0; i < len; i++)
246                {
247                    //divide by strokeWidth to take care of the difference between Svg and WPF
248                    dashArray.Add(list.GetItem(i).Value / strokeWidth);
249                }
250
251                return dashArray;
252            }
253        }
254
255        private double GetDashOffset(double strokeWidth)
256        {
257            string dashOffset = _element.GetPropertyValue("stroke-dashoffset");
258            if (dashOffset.Length > 0)
259            {
260                //divide by strokeWidth to take care of the difference between Svg and GDI+
261                SvgLength dashOffsetLength = new SvgLength(_element, "stroke-dashoffset",
262                    SvgLengthDirection.Viewport, dashOffset);
263                return dashOffsetLength.Value;
264            }
265            else
266            {
267                return 0;
268            }
269        }
270
271        private WpfFill GetPaintFill(string uri)
272        {
273            string absoluteUri = _element.ResolveUri(uri);
274
275            if (_element.Imported && _element.ImportDocument != null &&
276                _element.ImportNode != null)
277            {
278                // We need to determine whether the provided URI refers to element in the
279                // original document or in the current document...
280                SvgStyleableElement styleElm = _element.ImportNode as SvgStyleableElement;
281                if (styleElm != null)
282                {
283                    string propertyValue =
284                        styleElm.GetComputedStyle("").GetPropertyValue(_propertyName);
285
286                    if (!String.IsNullOrEmpty(propertyValue))
287                    {
288                        WpfSvgPaint importFill = new WpfSvgPaint(_context, styleElm, _propertyName);
289                        if (String.Equals(uri, importFill.Uri, StringComparison.OrdinalIgnoreCase))
290                        {
291                            WpfFill fill = WpfFill.CreateFill(_element.ImportDocument, absoluteUri);
292                            if (fill != null)
293                            {
294                                return fill;
295                            }
296                        }
297                    }
298                }
299            }
300
301            return WpfFill.CreateFill(_element.OwnerDocument, absoluteUri);
302        }
303
304        private Brush GetBrush(string propPrefix, bool setOpacity)
305        {
306            SvgPaint fill;
307            if (PaintType == SvgPaintType.None)
308            {
309                return null;
310            }
311            else if (PaintType == SvgPaintType.CurrentColor)
312            {
313                fill = new WpfSvgPaint(_context, _element, "color");
314            }
315            else
316            {
317                fill = this;
318            }
319
320            SvgPaintType paintType = fill.PaintType;
321            if (paintType == SvgPaintType.Uri     || paintType == SvgPaintType.UriCurrentColor ||
322                paintType == SvgPaintType.UriNone || paintType == SvgPaintType.UriRgbColor     ||
323                paintType == SvgPaintType.UriRgbColorIccColor)
324            {
325                _paintFill = GetPaintFill(fill.Uri);
326                if (_paintFill != null)
327                {
328                    Brush brush = _paintFill.GetBrush(_context);
329
330                    if (brush != null)
331                    {
332                        brush.Opacity = GetOpacity(propPrefix);
333                    }
334
335                    return brush;
336                }
337                else
338                {
339                    if (PaintType == SvgPaintType.UriNone || PaintType == SvgPaintType.Uri)
340                    {
341                        return null;
342                    }
343                    else if (PaintType == SvgPaintType.UriCurrentColor)
344                    {
345                        fill = new WpfSvgPaint(_context, _element, "color");
346                    }
347                    else
348                    {
349                        fill = this;
350                    }
351                }
352            }
353
354            if (fill == null || fill.RgbColor == null)
355            {
356                return null;
357            }
358
359            Color? solidColor = WpfConvert.ToColor(fill.RgbColor);
360            if (solidColor == null)
361            {
362                return null;
363            }
364
365            SolidColorBrush solidBrush = new SolidColorBrush(solidColor.Value);
366            //int opacity = GetOpacity(propPrefix);
367            //solidBrush.Color = Color.FromArgb(opacity, brush.Color);
368            if (setOpacity)
369            {
370                solidBrush.Opacity = GetOpacity(propPrefix);
371            }
372            return solidBrush;
373        }
374
375        #endregion
376    }
377}
Note: See TracBrowser for help on using the repository browser.