Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.Problems.GrammaticalOptimization/SharpVectorRenderingGdi/Gdi/GdiRendering.cs @ 13349

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

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

File size: 33.0 KB
Line 
1using System;
2using System.Xml;
3using System.Drawing;
4using System.Drawing.Drawing2D;
5using System.Text.RegularExpressions;
6
7using SharpVectors.Dom.Css;
8using SharpVectors.Dom.Svg;
9
10namespace SharpVectors.Renderers.Gdi
11{
12    public class GdiRendering : GdiRenderingBase
13    {
14        #region Private Fields
15
16        private Matrix _transformMatrix;
17        internal Color _uniqueColor;
18        internal GdiGraphicsContainer _graphicsContainer;
19
20        #endregion
21
22        #region Constructors and Destructor
23
24        public GdiRendering(SvgElement element)
25            : base(element)
26        {
27            _uniqueColor = Color.Empty;
28        }
29
30        #endregion
31
32        #region Public Properties
33
34        public Color UniqueColor
35        {
36            get
37            {
38                return _uniqueColor;
39            }
40        }
41
42        public Matrix TransformMatrix
43        {
44            get
45            {
46                return _transformMatrix;
47            }
48            set
49            {
50                _transformMatrix = value;
51            }
52        }
53
54        #endregion
55
56        #region Public Methods
57
58        public override void BeforeRender(GdiGraphicsRenderer renderer)
59        {
60            if (renderer == null)
61            {
62                return;
63            }
64
65            if (_uniqueColor.IsEmpty)
66                _uniqueColor = renderer.GetNextColor(element);
67
68            GdiGraphicsWrapper graphics = renderer.GraphicsWrapper;
69            if (graphics == null)
70            {
71                return;
72            }
73
74            _graphicsContainer = graphics.BeginContainer();
75            SetQuality(graphics);
76            Transform(graphics);
77            Clip(graphics);
78        }
79
80        public override void AfterRender(GdiGraphicsRenderer renderer)
81        {
82            if (renderer == null)
83            {
84                return;
85            }
86
87            GdiGraphicsWrapper graphics = renderer.GraphicsWrapper;
88            if (graphics == null)
89            {
90                return;
91            }
92
93            graphics.EndContainer(_graphicsContainer);
94        }
95
96        #endregion
97
98        #region Public Static Methods
99
100        public static GdiRendering Create(ISvgElement element)
101        {
102            if (element == null)
103            {
104                return null;
105            }
106
107            SvgRenderingHint hint = element.RenderingHint;
108            // For the shapes and text contents...
109            if (hint == SvgRenderingHint.Shape)
110            {
111                return new GdiPathRendering((SvgElement)element);
112            }
113            if (hint == SvgRenderingHint.Text)
114            {
115                return new GdiTextRendering((SvgElement)element);
116            }
117
118            string localName = element.LocalName;
119            if (String.IsNullOrEmpty(localName))
120            {
121                return new GdiRendering((SvgElement)element);
122            }
123
124            switch (localName)
125            {
126                case "svg":
127                    return new GdiRootRendering((SvgElement)element);
128                case "image":
129                    return new GdiImageRendering((SvgElement)element);
130                case "marker":
131                    return new GdiMarkerRendering((SvgElement)element);
132            }
133
134            return new GdiRendering((SvgElement)element);
135        }
136
137        /// <summary>
138        /// Generates a new <see cref="RenderingNode">RenderingNode</see> that
139        /// corresponds to the given Uri.
140        /// </summary>
141        /// <param name="baseUri">
142        /// The base Uri.
143        /// </param>
144        /// <param name="url">
145        /// The url.
146        /// </param>
147        /// <returns>
148        /// The generated <see cref="RenderingNode">RenderingNode</see> that
149        /// corresponds to the given Uri.
150        /// </returns>
151        public static GdiRendering CreateByUri(SvgDocument document, string baseUri, string url)
152        {
153            if (url.StartsWith("#"))
154            {
155                // do nothing
156            }
157            else if (baseUri != "")
158            {
159                Uri absoluteUri = new Uri(new Uri(baseUri), url);
160                url = absoluteUri.AbsoluteUri;
161            }
162            else
163            {
164                // TODO: Handle xml:base here?       
165                // Right now just skip this... it can't be resolved, must assume it is absolute
166            }
167            ISvgElement elm = document.GetNodeByUri(url) as ISvgElement;
168
169            if (elm != null)
170            {
171                return GdiRendering.Create(elm);
172            }
173            else
174            {
175                return null;
176            }
177        }
178
179        #endregion
180
181        #region Protected Methods
182
183        protected void Clip(GdiGraphicsWrapper gr)
184        {
185            if (element == null)
186            {
187                return;
188            }
189
190            SvgRenderingHint hint = element.RenderingHint;
191
192            // todo: should we correct the clipping to adjust to the off-one-pixel drawing?
193            gr.TranslateClip(1, 1);
194
195            #region Clip with clip
196            // see http://www.w3.org/TR/SVG/masking.html#OverflowAndClipProperties
197            if (element is ISvgSvgElement    || element is ISvgMarkerElement ||
198                element is ISvgSymbolElement || element is ISvgPatternElement)
199            {
200                // check overflow property
201                CssValue overflow = ((SvgElement)element).GetComputedCssValue("overflow", String.Empty) as CssValue;
202                // TODO: clip can have "rect(10 10 auto 10)"
203                CssPrimitiveValue clip = ((SvgElement)element).GetComputedCssValue("clip", String.Empty) as CssPrimitiveValue;
204
205                string sOverflow = null;
206
207                if (overflow != null || overflow.CssText == "")
208                {
209                    sOverflow = overflow.CssText;
210                }
211                else
212                {
213                    if (this is ISvgSvgElement)
214                        sOverflow = "hidden";
215                }
216
217                if (sOverflow != null)
218                {
219                    // "If the 'overflow' property has a value other than hidden or scroll, the property has no effect (i.e., a clipping rectangle is not created)."
220                    if (sOverflow == "hidden" || sOverflow == "scroll")
221                    {
222                        RectangleF clipRect = RectangleF.Empty;
223                        if (clip != null && clip.PrimitiveType == CssPrimitiveType.Rect)
224                        {
225                            if (element is ISvgSvgElement)
226                            {
227                                ISvgSvgElement svgElement = (ISvgSvgElement)element;
228                                SvgRect viewPort = svgElement.Viewport as SvgRect;
229                                clipRect = GdiConverter.ToRectangle(viewPort);
230                                ICssRect clipShape = (CssRect)clip.GetRectValue();
231                                if (clipShape.Top.PrimitiveType != CssPrimitiveType.Ident)
232                                    clipRect.Y += (float)clipShape.Top.GetFloatValue(CssPrimitiveType.Number);
233                                if (clipShape.Left.PrimitiveType != CssPrimitiveType.Ident)
234                                    clipRect.X += (float)clipShape.Left.GetFloatValue(CssPrimitiveType.Number);
235                                if (clipShape.Right.PrimitiveType != CssPrimitiveType.Ident)
236                                    clipRect.Width = (clipRect.Right - clipRect.X) - (float)clipShape.Right.GetFloatValue(CssPrimitiveType.Number);
237                                if (clipShape.Bottom.PrimitiveType != CssPrimitiveType.Ident)
238                                    clipRect.Height = (clipRect.Bottom - clipRect.Y) - (float)clipShape.Bottom.GetFloatValue(CssPrimitiveType.Number);
239                            }
240                        }
241                        else if (clip == null || (clip.PrimitiveType == CssPrimitiveType.Ident && clip.GetStringValue() == "auto"))
242                        {
243                            if (element is ISvgSvgElement)
244                            {
245                                ISvgSvgElement svgElement = (ISvgSvgElement)element;
246                                SvgRect viewPort = svgElement.Viewport as SvgRect;
247                                clipRect = GdiConverter.ToRectangle(viewPort);
248                            }
249                            else if (element is ISvgMarkerElement ||
250                              element is ISvgSymbolElement ||
251                              element is ISvgPatternElement)
252                            {
253                                // TODO: what to do here?
254                            }
255                        }
256                        if (clipRect != RectangleF.Empty)
257                        {
258                            gr.SetClip(clipRect);
259                        }
260                    }
261                }
262            }
263            #endregion
264
265            #region Clip with clip-path
266
267            // see: http://www.w3.org/TR/SVG/masking.html#EstablishingANewClippingPath
268
269            if (hint == SvgRenderingHint.Shape || hint == SvgRenderingHint.Text ||
270                hint == SvgRenderingHint.Clipping || hint == SvgRenderingHint.Masking ||
271                hint == SvgRenderingHint.Containment)
272            {
273                CssPrimitiveValue clipPath = ((SvgElement)element).GetComputedCssValue("clip-path", String.Empty) as CssPrimitiveValue;
274
275                if (clipPath != null && clipPath.PrimitiveType == CssPrimitiveType.Uri)
276                {
277                    string absoluteUri = ((SvgElement)element).ResolveUri(clipPath.GetStringValue());
278
279                    SvgClipPathElement eClipPath = element.OwnerDocument.GetNodeByUri(absoluteUri) as SvgClipPathElement;
280
281                    if (eClipPath != null)
282                    {
283                        GraphicsPath gpClip = CreateClippingRegion(eClipPath);
284
285                        RectangleF clipBounds = gpClip != null ? gpClip.GetBounds() : RectangleF.Empty;
286
287                        if (clipBounds.Width == 0 || clipBounds.Height == 0)
288                        {
289                            return;
290                        }
291
292                        SvgUnitType pathUnits = (SvgUnitType)eClipPath.ClipPathUnits.AnimVal;
293
294                        if (pathUnits == SvgUnitType.ObjectBoundingBox)
295                        {
296                            SvgTransformableElement transElement = element as SvgTransformableElement;
297
298                            if (transElement != null)
299                            {
300                                ISvgRect bbox = transElement.GetBBox();
301
302                                // scale clipping path
303                                Matrix matrix = new Matrix();
304                                matrix.Scale((float)bbox.Width, (float)bbox.Height);
305                                gpClip.Transform(matrix);
306                                gr.SetClip(gpClip);
307
308                                // offset clip
309                                gr.TranslateClip((float)bbox.X, (float)bbox.Y);
310                            }
311                            else
312                            {
313                                throw new NotImplementedException("clip-path with SvgUnitType.ObjectBoundingBox "
314                                  + "not supported for this type of element: " + element.GetType());
315                            }
316                        }
317                        else
318                        {
319                            gr.SetClip(gpClip);
320                        }
321
322                        gpClip.Dispose();
323                        gpClip = null;
324                    }
325                }
326            }
327            #endregion
328        }
329
330        protected void SetQuality(GdiGraphicsWrapper gr)
331        {
332            Graphics graphics = gr.Graphics;
333
334            string colorRendering = ((SvgElement)element).GetComputedStringValue("color-rendering", String.Empty);
335            switch (colorRendering)
336            {
337                case "optimizeSpeed":
338                    graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighSpeed;
339                    break;
340                case "optimizeQuality":
341                    graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
342                    break;
343                default:
344                    // "auto"
345                    // todo: could use AssumeLinear for slightly better
346                    graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.Default;
347                    break;
348            }
349
350            if (element is SvgTextContentElement)
351            {
352                // Unfortunately the text rendering hints are not applied because the
353                // text path is recorded and painted to the Graphics object as a path
354                // not as text.
355                string textRendering = ((SvgElement)element).GetComputedStringValue("text-rendering", String.Empty);
356                switch (textRendering)
357                {
358                    case "optimizeSpeed":
359                        graphics.SmoothingMode = SmoothingMode.HighSpeed;
360                        //graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.SingleBitPerPixel;
361                        break;
362                    case "optimizeLegibility":
363                        graphics.SmoothingMode = SmoothingMode.HighQuality;
364                        //graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
365                        break;
366                    case "geometricPrecision":
367                        graphics.SmoothingMode = SmoothingMode.AntiAlias;
368                        //graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
369                        break;
370                    default:
371                        // "auto"
372                        graphics.SmoothingMode = SmoothingMode.AntiAlias;
373                        //graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.SystemDefault;
374                        break;
375                }
376            }
377            else
378            {
379                string shapeRendering = ((SvgElement)element).GetComputedStringValue("shape-rendering", String.Empty);
380                switch (shapeRendering)
381                {
382                    case "optimizeSpeed":
383                        graphics.SmoothingMode = SmoothingMode.HighSpeed;
384                        break;
385                    case "crispEdges":
386                        graphics.SmoothingMode = SmoothingMode.None;
387                        break;
388                    case "geometricPrecision":
389                        graphics.SmoothingMode = SmoothingMode.HighQuality;
390                        break;
391                    default:
392                        // "auto"
393                        graphics.SmoothingMode = SmoothingMode.AntiAlias;
394                        break;
395                }
396            }
397        }
398
399        protected void Transform(GdiGraphicsWrapper gr)
400        {
401            if (element is ISvgTransformable)
402            {
403                if (_transformMatrix == null)
404                {
405                    ISvgTransformable transElm = (ISvgTransformable)element;
406                    SvgTransformList svgTList  = (SvgTransformList)transElm.Transform.AnimVal;
407                    SvgMatrix svgMatrix = ((SvgTransformList)transElm.Transform.AnimVal).TotalMatrix;
408
409                    _transformMatrix = new Matrix((float)svgMatrix.A, (float)svgMatrix.B, (float)svgMatrix.C,
410                      (float)svgMatrix.D, (float)svgMatrix.E, (float)svgMatrix.F);
411                }
412                gr.Transform = _transformMatrix;
413            }
414        }
415
416        protected void FitToViewbox(GdiGraphicsWrapper graphics, RectangleF elmRect)
417        {
418            if (element is ISvgFitToViewBox)
419            {
420                ISvgFitToViewBox fitToVBElm = (ISvgFitToViewBox)element;
421                SvgPreserveAspectRatio spar = (SvgPreserveAspectRatio)fitToVBElm.PreserveAspectRatio.AnimVal;
422
423                double[] translateAndScale = spar.FitToViewBox(
424                  (SvgRect)fitToVBElm.ViewBox.AnimVal,
425                  new SvgRect(elmRect.X, elmRect.Y, elmRect.Width, elmRect.Height));
426                graphics.TranslateTransform((float)translateAndScale[0], (float)translateAndScale[1]);
427                graphics.ScaleTransform((float)translateAndScale[2], (float)translateAndScale[3]);
428            }
429        }
430
431        #endregion
432
433        #region Private Methods
434
435        private GraphicsPath CreateClippingRegion(SvgClipPathElement clipPath)
436        {
437            GraphicsPath path = new GraphicsPath();
438
439            foreach (XmlNode node in clipPath.ChildNodes)
440            {
441                if (node.NodeType != XmlNodeType.Element)
442                {
443                    continue;
444                }
445
446                // Handle a case where the clip element has "use" element as a child...
447                if (String.Equals(node.LocalName, "use"))
448                {
449                    SvgUseElement useElement = (SvgUseElement)node;
450
451                    XmlElement refEl = useElement.ReferencedElement;
452                    if (refEl != null)
453                    {
454                        XmlElement refElParent = (XmlElement)refEl.ParentNode;
455                        useElement.OwnerDocument.Static = true;
456                        useElement.CopyToReferencedElement(refEl);
457                        refElParent.RemoveChild(refEl);
458                        useElement.AppendChild(refEl);
459
460                        foreach (XmlNode useChild in useElement.ChildNodes)
461                        {
462                            if (useChild.NodeType != XmlNodeType.Element)
463                            {
464                                continue;
465                            }
466
467                            SvgStyleableElement element = useChild as SvgStyleableElement;
468                            if (element != null && element.RenderingHint == SvgRenderingHint.Shape)
469                            {
470                                GraphicsPath childPath = CreatePath(element);
471
472                                if (childPath != null)
473                                {
474                                    string clipRule = element.GetPropertyValue("clip-rule");
475                                    path.FillMode = (clipRule == "evenodd") ? FillMode.Alternate : FillMode.Winding;
476
477                                    path.AddPath(childPath, true);
478                                }
479                            }
480                        }
481
482                        useElement.RemoveChild(refEl);
483                        useElement.RestoreReferencedElement(refEl);
484                        refElParent.AppendChild(refEl);
485                        useElement.OwnerDocument.Static = false;
486                    }
487                }
488                else
489                {
490                    SvgStyleableElement element = node as SvgStyleableElement;
491                    if (element != null && element.RenderingHint == SvgRenderingHint.Shape)
492                    {
493                        GraphicsPath childPath = CreatePath(element);
494
495                        if (childPath != null)
496                        {
497                            string clipRule = element.GetPropertyValue("clip-rule");
498                            path.FillMode = (clipRule == "evenodd") ? FillMode.Alternate : FillMode.Winding;
499
500                            path.AddPath(childPath, true);
501                        }
502                    }
503                }
504            }
505
506            return path;
507        }
508
509        #endregion
510
511        #region GraphicsPath Methods
512
513        public static GraphicsPath CreatePath(ISvgElement element)
514        {
515            if (element == null || element.RenderingHint != SvgRenderingHint.Shape)
516            {
517                return null;
518            }
519
520            string localName = element.LocalName;
521            switch (localName)
522            {
523                case "ellipse":
524                    return CreatePath((SvgEllipseElement)element);
525                case "rect":
526                    return CreatePath((SvgRectElement)element);
527                case "line":
528                    return CreatePath((SvgLineElement)element);
529                case "path":
530                    return CreatePath((SvgPathElement)element);
531                case "circle":
532                    return CreatePath((SvgCircleElement)element);
533                case "polyline":
534                    return CreatePath((SvgPolylineElement)element);
535                case "polygon":
536                    return CreatePath((SvgPolygonElement)element);
537            }
538
539            return null;
540        }
541
542        #region SvgEllipseElement Path
543
544        public static GraphicsPath CreatePath(SvgEllipseElement element)
545        {
546            GraphicsPath gp = new GraphicsPath();
547            float _cx = (float)element.Cx.AnimVal.Value;
548            float _cy = (float)element.Cy.AnimVal.Value;
549            float _rx = (float)element.Rx.AnimVal.Value;
550            float _ry = (float)element.Ry.AnimVal.Value;
551
552            /*if (_cx <= 1 && _cy <= 1 && _rx <= 1 && _ry <= 1)
553            {
554                gp.AddEllipse(_cx-_rx, _cy-_ry, _rx*2, _ry*2);
555            }
556            else
557            {
558                gp.AddEllipse(_cx-_rx, _cy-_ry, _rx*2 - 1, _ry*2 - 1);
559            }*/
560            gp.AddEllipse(_cx - _rx, _cy - _ry, _rx * 2, _ry * 2);
561
562            return gp;
563        }
564
565        #endregion
566
567        #region SvgRectElement Path
568
569        public static GraphicsPath CreatePath(SvgRectElement element)
570        {
571            GraphicsPath gp = new GraphicsPath();
572
573            RectangleF rect = new RectangleF((float)element.X.AnimVal.Value,
574                (float)element.Y.AnimVal.Value, (float)element.Width.AnimVal.Value,
575                (float)element.Height.AnimVal.Value);
576
577            float rx = (float)element.Rx.AnimVal.Value;
578            float ry = (float)element.Ry.AnimVal.Value;
579
580            if (rx == 0F && ry == 0F)
581            {
582                gp.AddRectangle(rect);
583            }
584            else
585            {
586                AddRoundedRect(gp, rect, rx, ry);
587            }
588
589            return gp;
590        }
591
592        public static void AddRoundedRect(GraphicsPath path, RectangleF rect, float rx, float ry)
593        {
594            if (rx == 0F) rx = ry;
595            else if (ry == 0F) ry = rx;
596
597            rx = Math.Min(rect.Width / 2, rx);
598            ry = Math.Min(rect.Height / 2, ry);
599
600            float a = rect.X + rect.Width - rx;
601            path.AddLine(rect.X + rx, rect.Y, a, rect.Y);
602            path.AddArc(a - rx, rect.Y, rx * 2, ry * 2, 270, 90);
603
604            float right = rect.X + rect.Width;  // rightmost X
605            float b = rect.Y + rect.Height - ry;
606
607            path.AddLine(right, rect.Y + ry, right, b);
608            path.AddArc(right - rx * 2, b - ry, rx * 2, ry * 2, 0, 90);
609
610            path.AddLine(right - rx, rect.Y + rect.Height, rect.X + rx, rect.Y + rect.Height);
611            path.AddArc(rect.X, b - ry, rx * 2, ry * 2, 90, 90);
612
613            path.AddLine(rect.X, b, rect.X, rect.Y + ry);
614            path.AddArc(rect.X, rect.Y, rx * 2, ry * 2, 180, 90);
615        }
616
617        #endregion
618
619        #region SvgLineElement Path
620
621        public static GraphicsPath CreatePath(SvgLineElement element)
622        {
623            GraphicsPath gp = new GraphicsPath();
624
625            gp.AddLine((float)element.X1.AnimVal.Value, (float)element.Y1.AnimVal.Value,
626                (float)element.X2.AnimVal.Value, (float)element.Y2.AnimVal.Value);
627
628            return gp;
629        }
630
631        #endregion
632
633        #region SvgPathElement Path
634
635        public static GraphicsPath CreatePath(SvgPathElement element)
636        {
637            GraphicsPath gp = new GraphicsPath();
638
639            SvgPointF initPoint = new SvgPointF(0, 0);
640            SvgPointF lastPoint = new SvgPointF(0, 0);
641
642            ISvgPathSeg segment = null;
643            SvgPathSegMoveto pathMoveTo = null;
644            SvgPathSegLineto pathLineTo = null;
645            SvgPathSegCurveto pathCurveTo = null;
646            SvgPathSegArc pathArc = null;
647
648            ISvgPathSegList segments = element.PathSegList;
649            int nElems = segments.NumberOfItems;
650
651            for (int i = 0; i < nElems; i++)
652            {
653                segment = segments.GetItem(i);
654
655                if (DynamicCast.Cast(segment, out pathMoveTo))
656                {
657                    //SvgPathSegMoveto seg = (SvgPathSegMoveto)segment;
658                    gp.StartFigure();
659                    lastPoint = initPoint = pathMoveTo.AbsXY;
660                }
661                else if (DynamicCast.Cast(segment, out pathLineTo))
662                {
663                    //SvgPathSegLineto seg = (SvgPathSegLineto)segment;
664                    SvgPointF p = pathLineTo.AbsXY;
665                    gp.AddLine(lastPoint.X, lastPoint.Y, p.X, p.Y);
666
667                    lastPoint = p;
668                }
669                else if (DynamicCast.Cast(segment, out pathCurveTo))
670                {
671                    // SvgPathSegCurveto seg = (SvgPathSegCurveto)segment;
672                    SvgPointF xy = pathCurveTo.AbsXY;
673                    SvgPointF x1y1 = pathCurveTo.CubicX1Y1;
674                    SvgPointF x2y2 = pathCurveTo.CubicX2Y2;
675                    gp.AddBezier(lastPoint.X, lastPoint.Y, x1y1.X, x1y1.Y, x2y2.X, x2y2.Y, xy.X, xy.Y);
676
677                    lastPoint = xy;
678                }
679                else if (DynamicCast.Cast(segment, out pathArc))
680                {
681                    //SvgPathSegArc seg = (SvgPathSegArc)segment;
682                    SvgPointF p = pathArc.AbsXY;
683                    if (lastPoint.Equals(p))
684                    {
685                        // If the endpoints (x, y) and (x0, y0) are identical, then this
686                        // is equivalent to omitting the elliptical arc segment entirely.
687                    }
688                    else if (pathArc.R1 == 0 || pathArc.R2 == 0)
689                    {
690                        // Ensure radii are valid
691                        gp.AddLine(lastPoint.X, lastPoint.Y, p.X, p.Y);
692                    }
693                    else
694                    {
695                        CalculatedArcValues calcValues = pathArc.GetCalculatedArcValues();
696
697                        GraphicsPath gp2 = new GraphicsPath();
698                        gp2.StartFigure();
699                        gp2.AddArc((float)(calcValues.Cx - calcValues.CorrRx),
700                            (float)(calcValues.Cy - calcValues.CorrRy),
701                            (float)calcValues.CorrRx * 2, (float)calcValues.CorrRy * 2,
702                            (float)calcValues.AngleStart, (float)calcValues.AngleExtent);
703
704                        Matrix matrix = new Matrix();
705                        matrix.Translate(-(float)calcValues.Cx, -(float)calcValues.Cy);
706                        gp2.Transform(matrix);
707
708                        matrix = new Matrix();
709                        matrix.Rotate((float)pathArc.Angle);
710                        gp2.Transform(matrix);
711
712                        matrix = new Matrix();
713                        matrix.Translate((float)calcValues.Cx, (float)calcValues.Cy);
714                        gp2.Transform(matrix);
715
716                        gp.AddPath(gp2, true);
717                    }
718
719                    lastPoint = p;
720                }
721                else if (segment is SvgPathSegClosePath)
722                {
723                    gp.CloseFigure();
724                    lastPoint = initPoint;
725                }
726            }
727
728            string fillRule = element.GetPropertyValue("fill-rule");
729            if (fillRule == "evenodd")
730                gp.FillMode = FillMode.Alternate;
731            else
732                gp.FillMode = FillMode.Winding;
733
734            return gp;
735        }
736
737        #endregion
738
739        #region SvgCircleElement Path
740
741        public static GraphicsPath CreatePath(SvgCircleElement element)
742        {
743            GraphicsPath gp = new GraphicsPath();
744
745            float _cx = (float)element.Cx.AnimVal.Value;
746            float _cy = (float)element.Cy.AnimVal.Value;
747            float _r = (float)element.R.AnimVal.Value;
748
749            gp.AddEllipse(_cx - _r, _cy - _r, _r * 2, _r * 2);
750
751            return gp;
752        }
753
754        #endregion
755
756        #region SvgPolylineElement Path
757
758        public static GraphicsPath CreatePath(SvgPolylineElement element)
759        {
760            GraphicsPath gp = new GraphicsPath();
761
762            ISvgPointList list = element.AnimatedPoints;
763            ulong nElems = list.NumberOfItems;
764
765            PointF[] points = new PointF[nElems];
766
767            for (uint i = 0; i < nElems; i++)
768            {
769                points[i] = new PointF((float)list.GetItem(i).X, (float)list.GetItem(i).Y);
770            }
771
772            gp.AddLines(points);
773
774            string fillRule = element.GetPropertyValue("fill-rule");
775            if (fillRule == "evenodd")
776                gp.FillMode = FillMode.Alternate;
777            else
778                gp.FillMode = FillMode.Winding;
779
780            return gp;
781        }
782
783        #endregion
784
785        #region SvgPolygonElement Path
786
787        public static GraphicsPath CreatePath(SvgPolygonElement element)
788        {
789            GraphicsPath gp = new GraphicsPath();
790
791            ISvgPointList list = element.AnimatedPoints;
792            ulong nElems = list.NumberOfItems;
793
794            PointF[] points = new PointF[nElems];
795
796            for (uint i = 0; i < nElems; i++)
797            {
798                points[i] = new PointF((float)list.GetItem(i).X, (float)list.GetItem(i).Y);
799            }
800
801            gp.AddPolygon(points);
802
803            string fillRule = element.GetPropertyValue("fill-rule");
804            if (fillRule == "evenodd")
805                gp.FillMode = FillMode.Alternate;
806            else
807                gp.FillMode = FillMode.Winding;
808
809            return gp;
810        }
811
812        #endregion
813
814        #endregion
815
816        #region Marker Methods
817
818        protected static string ExtractMarkerUrl(string propValue)
819        {
820            Regex reUrl = new Regex(@"^url\((?<uri>.+)\)$");
821            Match match = reUrl.Match(propValue);
822            if (match.Success)
823            {
824                return match.Groups["uri"].Value;
825            }
826            else
827            {
828                return String.Empty;
829            }
830        }
831
832        protected static void PaintMarkers(GdiGraphicsRenderer renderer,
833            SvgStyleableElement styleElm, GdiGraphicsWrapper gr)
834        {
835            // OPTIMIZE
836
837            if (styleElm is ISharpMarkerHost)
838            {
839                string markerStartUrl = ExtractMarkerUrl(styleElm.GetPropertyValue("marker-start", "marker"));
840                string markerMiddleUrl = ExtractMarkerUrl(styleElm.GetPropertyValue("marker-mid", "marker"));
841                string markerEndUrl = ExtractMarkerUrl(styleElm.GetPropertyValue("marker-end", "marker"));
842
843                if (markerStartUrl.Length > 0)
844                {
845                    GdiMarkerRendering grNode = CreateByUri(styleElm.OwnerDocument,
846                        styleElm.BaseURI, markerStartUrl) as GdiMarkerRendering;
847                    if (grNode != null)
848                    {
849                        grNode.PaintMarker(renderer, gr, SvgMarkerPosition.Start, styleElm);
850                    }
851                }
852
853                if (markerMiddleUrl.Length > 0)
854                {
855                    // TODO markerMiddleUrl != markerStartUrl
856                    GdiMarkerRendering grNode = CreateByUri(styleElm.OwnerDocument,
857                        styleElm.BaseURI, markerMiddleUrl) as GdiMarkerRendering;
858                    if (grNode != null)
859                    {
860                        grNode.PaintMarker(renderer, gr, SvgMarkerPosition.Mid, styleElm);
861                    }
862                }
863
864                if (markerEndUrl.Length > 0)
865                {
866                    // TODO: markerEndUrl != markerMiddleUrl
867                    GdiMarkerRendering grNode = CreateByUri(styleElm.OwnerDocument,
868                        styleElm.BaseURI, markerEndUrl) as GdiMarkerRendering;
869                    if (grNode != null)
870                    {
871                        grNode.PaintMarker(renderer, gr, SvgMarkerPosition.End, styleElm);
872                    }
873                }
874            }
875        }
876
877        #endregion
878
879        #region IDisposable Members
880
881        protected override void Dispose(bool disposing)
882        {
883            if (disposing)
884            {
885                if (_transformMatrix != null)
886                {
887                    _transformMatrix.Dispose();
888                    _transformMatrix = null;
889                }
890            }
891
892            base.Dispose(disposing);
893        }
894
895        #endregion
896    }
897}
Note: See TracBrowser for help on using the repository browser.