public void Visit(ISvgUseElement element)
        {
            SvgUseElement useElement = (SvgUseElement)element;
            SvgDocument   document   = useElement.OwnerDocument;
            XmlElement    refEl      = useElement.ReferencedElement;

            if (refEl == null)
            {
                return;
            }

            bool isImported = false;

            // For the external node, the documents are different, and we may not be
            // able to insert this node, so we first import it...
            if (useElement.OwnerDocument != refEl.OwnerDocument)
            {
                XmlElement importedNode =
                    useElement.OwnerDocument.ImportNode(refEl, true) as XmlElement;

                if (importedNode != null)
                {
                    SvgElement importedSvgElement = importedNode as SvgElement;
                    if (importedSvgElement != null)
                    {
                        importedSvgElement.Imported       = true;
                        importedSvgElement.ImportNode     = refEl as SvgElement;
                        importedSvgElement.ImportDocument = refEl.OwnerDocument as SvgDocument;
                    }

                    refEl      = importedNode;
                    isImported = true;
                }
            }
            XmlElement refElParent = (XmlElement)refEl.ParentNode;

            useElement.OwnerDocument.Static = true;
            useElement.CopyToReferencedElement(refEl);
            if (!isImported) // if imported, we do not need to remove it...
            {
                refElParent.RemoveChild(refEl);
            }
            useElement.AppendChild(refEl);

            // Now, render the use element...
            var refElement = useElement?.FirstChild;

            if (refElement is IElementVisitorTarget evt)
            {
                evt.Accept(this);
            }

            useElement.RemoveChild(refEl);
            useElement.RestoreReferencedElement(refEl);
            if (!isImported)
            {
                refElParent.AppendChild(refEl);
            }
            useElement.OwnerDocument.Static = false;
        }
        private void RenderUseElement(ISvgElement svgElement)
        {
            SvgUseElement useElement = (SvgUseElement)svgElement;

            int hashCode = useElement.OuterXml.GetHashCode();

            if (!this.BeginUseElement(hashCode))
            {
                return;
            }

            SvgDocument document = useElement.OwnerDocument;

            XmlElement refEl = useElement.ReferencedElement;

            if (refEl == null)
            {
                this.EndUseElement(hashCode);
                return;
            }

            // For the external node, the documents are different, and we may not be
            // able to insert this node, so we first import it...
            if (useElement.OwnerDocument != refEl.OwnerDocument)
            {
                XmlElement importedNode = useElement.OwnerDocument.ImportNode(refEl, true) as XmlElement;

                if (importedNode != null)
                {
                    SvgElement importedSvgElement = importedNode as SvgElement;
                    if (importedSvgElement != null)
                    {
                        importedSvgElement.Imported       = true;
                        importedSvgElement.ImportNode     = refEl as SvgElement;
                        importedSvgElement.ImportDocument = refEl.OwnerDocument as SvgDocument;
                    }

                    refEl = importedNode;
                }
            }
            else
            {
                // For elements/nodes within the same document, clone it.
                refEl = (XmlElement)refEl.CloneNode(true);
            }
            // Reset any ID on the cloned/copied element to avoid duplication of IDs.
            //           refEl.SetAttribute("id", "");

            useElement.OwnerDocument.Static = true;
            useElement.CopyToReferencedElement(refEl);
            useElement.AppendChild(refEl);

            // Now, render the use element...
            this.RenderElement(svgElement);

            useElement.RemoveChild(refEl);
            useElement.RestoreReferencedElement(refEl);

            this.EndUseElement(hashCode);
        }
        private void RenderUseElement(ISvgElement svgElement)
        {
            SvgUseElement useElement = (SvgUseElement)svgElement;

            XmlElement refEl = useElement.ReferencedElement;

            if (refEl == null)
            {
                return;
            }
            XmlElement refElParent = (XmlElement)refEl.ParentNode;

            useElement.OwnerDocument.Static = true;
            useElement.CopyToReferencedElement(refEl);
            refElParent.RemoveChild(refEl);
            useElement.AppendChild(refEl);

            this.RenderElement(svgElement);

            useElement.RemoveChild(refEl);
            useElement.RestoreReferencedElement(refEl);
            refElParent.AppendChild(refEl);
            useElement.OwnerDocument.Static = false;
        }
Exemple #4
0
        private void AggregateChildren(SvgAElement aElement, WpfDrawingContext context, float opacity)
        {
            _isAggregated = false;

            if (aElement == null || aElement.ChildNodes == null)
            {
                return;
            }

            string aggregatedFill = aElement.GetAttribute("fill");
            bool   isFillFound    = !String.IsNullOrEmpty(aggregatedFill);

            SvgStyleableElement paintElement = null;

            if (isFillFound)
            {
                paintElement = aElement;
            }

            XmlNode targetNode = aElement;

            // Check if the children of the link are wrapped in a Group Element...
            if (aElement.ChildNodes.Count == 1)
            {
                SvgGElement groupElement = aElement.ChildNodes[0] as SvgGElement;
                if (groupElement != null)
                {
                    targetNode = groupElement;
                }
            }

            WpfDrawingSettings settings = context.Settings;

            GeometryCollection geomColl = new GeometryCollection();

            foreach (XmlNode node in targetNode.ChildNodes)
            {
                if (node.NodeType != XmlNodeType.Element)
                {
                    continue;
                }

                // Handle a case where the clip element has "use" element as a child...
                if (String.Equals(node.LocalName, "use"))
                {
                    SvgUseElement useElement = (SvgUseElement)node;

                    XmlElement refEl = useElement.ReferencedElement;
                    if (refEl != null)
                    {
                        XmlElement refElParent = (XmlElement)refEl.ParentNode;
                        useElement.OwnerDocument.Static = true;
                        useElement.CopyToReferencedElement(refEl);
                        refElParent.RemoveChild(refEl);
                        useElement.AppendChild(refEl);

                        foreach (XmlNode useChild in useElement.ChildNodes)
                        {
                            if (useChild.NodeType != XmlNodeType.Element)
                            {
                                continue;
                            }

                            SvgStyleableElement element = useChild as SvgStyleableElement;
                            if (element != null && element.RenderingHint == SvgRenderingHint.Shape)
                            {
                                Geometry childPath = WpfRendering.CreateGeometry(element,
                                                                                 settings.OptimizePath);

                                if (childPath != null)
                                {
                                    if (isFillFound)
                                    {
                                        string elementFill = element.GetAttribute("fill");
                                        if (!String.IsNullOrEmpty(elementFill) &&
                                            !String.Equals(elementFill, aggregatedFill, StringComparison.OrdinalIgnoreCase))
                                        {
                                            return;
                                        }
                                    }
                                    else
                                    {
                                        aggregatedFill = element.GetAttribute("fill");
                                        isFillFound    = !String.IsNullOrEmpty(aggregatedFill);
                                        if (isFillFound)
                                        {
                                            paintElement = element;
                                        }
                                    }

                                    geomColl.Add(childPath);
                                }
                            }
                        }

                        useElement.RemoveChild(refEl);
                        useElement.RestoreReferencedElement(refEl);
                        refElParent.AppendChild(refEl);
                        useElement.OwnerDocument.Static = false;
                    }
                }
                //else if (String.Equals(node.LocalName, "g"))
                //{
                //}
                else
                {
                    SvgStyleableElement element = node as SvgStyleableElement;
                    if (element != null && element.RenderingHint == SvgRenderingHint.Shape)
                    {
                        Geometry childPath = WpfRendering.CreateGeometry(element,
                                                                         settings.OptimizePath);

                        if (childPath != null)
                        {
                            if (isFillFound)
                            {
                                string elementFill = element.GetAttribute("fill");
                                if (!String.IsNullOrEmpty(elementFill) &&
                                    !String.Equals(elementFill, aggregatedFill, StringComparison.OrdinalIgnoreCase))
                                {
                                    return;
                                }
                            }
                            else
                            {
                                aggregatedFill = element.GetAttribute("fill");
                                isFillFound    = !String.IsNullOrEmpty(aggregatedFill);
                                if (isFillFound)
                                {
                                    paintElement = element;
                                }
                            }

                            geomColl.Add(childPath);
                        }
                    }
                }
            }

            if (geomColl.Count == 0 || paintElement == null)
            {
                return;
            }

            _aggregatedFill = paintElement;
            _aggregatedGeom = geomColl;

            _isAggregated = true;
        }
        private GraphicsPath CreateClippingRegion(GdiGraphics graphics, SvgClipPathElement clipPath)
        {
            GraphicsPath path = new GraphicsPath();

            foreach (XmlNode node in clipPath.ChildNodes)
            {
                if (node.NodeType != XmlNodeType.Element)
                {
                    continue;
                }

                // Handle a case where the clip element has "use" element as a child...
                if (string.Equals(node.LocalName, "use"))
                {
                    SvgUseElement useElement = (SvgUseElement)node;

                    XmlElement refEl = useElement.ReferencedElement;
                    if (refEl != null)
                    {
                        XmlElement refElParent = (XmlElement)refEl.ParentNode;
                        useElement.OwnerDocument.Static = true;
                        useElement.CopyToReferencedElement(refEl);
                        refElParent.RemoveChild(refEl);
                        useElement.AppendChild(refEl);

                        foreach (XmlNode useChild in useElement.ChildNodes)
                        {
                            if (useChild.NodeType != XmlNodeType.Element)
                            {
                                continue;
                            }

                            SvgStyleableElement element = useChild as SvgStyleableElement;
                            if (element != null && element.RenderingHint == SvgRenderingHint.Shape)
                            {
                                GraphicsPath childPath = CreatePath(element);

                                if (childPath != null)
                                {
                                    string clipRule = element.GetPropertyValue("clip-rule");
                                    path.FillMode = (clipRule == "evenodd") ? FillMode.Alternate : FillMode.Winding;

                                    path.AddPath(childPath, true);
                                }
                            }
                        }

                        useElement.RemoveChild(refEl);
                        useElement.RestoreReferencedElement(refEl);
                        refElParent.AppendChild(refEl);
                        useElement.OwnerDocument.Static = false;
                    }
                }
                else
                {
                    SvgStyleableElement element = node as SvgStyleableElement;
                    if (element != null)
                    {
                        if (element.RenderingHint == SvgRenderingHint.Shape)
                        {
                            GraphicsPath childPath = CreatePath(element);

                            if (childPath != null)
                            {
                                string clipRule = element.GetPropertyValue("clip-rule");
                                path.FillMode = (clipRule == "evenodd") ? FillMode.Alternate : FillMode.Winding;

                                path.AddPath(childPath, true);
                            }
                        }
                        else if (element.RenderingHint == SvgRenderingHint.Text)
                        {
                            GdiTextRendering textRendering = new GdiTextRendering(element);
                            textRendering.TextMode = GdiTextMode.Outlining;

                            GdiGraphicsRenderer renderer = new GdiGraphicsRenderer(graphics);

                            textRendering.BeforeRender(renderer);
                            textRendering.Render(renderer);
                            textRendering.AfterRender(renderer);

                            GraphicsPath childPath = textRendering.Path;
                            if (childPath != null)
                            {
                                string clipRule = element.GetPropertyValue("clip-rule");
                                path.FillMode = (clipRule == "evenodd") ? FillMode.Alternate : FillMode.Winding;

                                path.AddPath(childPath, true);
                            }
                        }
                    }
                }
            }

            return(path);
        }
        private GeometryCollection CreateClippingRegion(SvgClipPathElement clipPath,
                                                        WpfDrawingContext context)
        {
            GeometryCollection geomColl = new GeometryCollection();

            foreach (XmlNode node in clipPath.ChildNodes)
            {
                if (node.NodeType != XmlNodeType.Element)
                {
                    continue;
                }

                // Handle a case where the clip element has "use" element as a child...
                if (string.Equals(node.LocalName, "use"))
                {
                    SvgUseElement useElement = (SvgUseElement)node;

                    XmlElement refEl = useElement.ReferencedElement;
                    if (refEl != null)
                    {
                        XmlElement refElParent = (XmlElement)refEl.ParentNode;
                        useElement.OwnerDocument.Static = true;
                        useElement.CopyToReferencedElement(refEl);
                        refElParent.RemoveChild(refEl);
                        useElement.AppendChild(refEl);

                        foreach (XmlNode useChild in useElement.ChildNodes)
                        {
                            if (useChild.NodeType != XmlNodeType.Element)
                            {
                                continue;
                            }

                            SvgStyleableElement element = useChild as SvgStyleableElement;
                            if (element != null && element.RenderingHint == SvgRenderingHint.Shape)
                            {
                                Geometry childPath = CreateGeometry(element, context.OptimizePath);

                                if (childPath != null)
                                {
                                    geomColl.Add(childPath);
                                }
                            }
                        }

                        useElement.RemoveChild(refEl);
                        useElement.RestoreReferencedElement(refEl);
                        refElParent.AppendChild(refEl);
                        useElement.OwnerDocument.Static = false;
                    }
                }
                else
                {
                    SvgStyleableElement element = node as SvgStyleableElement;
                    if (element != null)
                    {
                        if (element.RenderingHint == SvgRenderingHint.Shape)
                        {
                            Geometry childPath = CreateGeometry(element, context.OptimizePath);

                            if (childPath != null)
                            {
                                geomColl.Add(childPath);
                            }
                        }
                        else if (element.RenderingHint == SvgRenderingHint.Text)
                        {
                            GeometryCollection textGeomColl = GetTextClippingRegion(element, context);
                            if (textGeomColl != null)
                            {
                                for (int i = 0; i < textGeomColl.Count; i++)
                                {
                                    geomColl.Add(textGeomColl[i]);
                                }
                            }
                        }
                    }
                }
            }

            return(geomColl);
        }
Exemple #7
0
        private void RenderUseElement(ISvgElement svgElement)
        {
            SvgUseElement useElement = (SvgUseElement)svgElement;

            int hashCode = 0; // useElement.OuterXml.GetHashCode();

            if (!this.BeginUseElement(useElement, out hashCode))
            {
                return;
            }

            SvgDocument document = useElement.OwnerDocument;

            XmlElement refEl = useElement.ReferencedElement;

            if (refEl == null)
            {
                this.EndUseElement(useElement, hashCode);
                return;
            }
            XmlElement refElParent = refEl.ParentNode as XmlElement;
            var        siblingNode = refEl.PreviousSibling;

            if (siblingNode != null && siblingNode.NodeType == XmlNodeType.Whitespace)
            {
                siblingNode = siblingNode.PreviousSibling;
            }

            // For the external node, the documents are different, and we may not be
            // able to insert this node, so we first import it...
            if (useElement.OwnerDocument != refEl.OwnerDocument)
            {
                var importedNode = useElement.OwnerDocument.ImportNode(refEl, true) as XmlElement;

                if (importedNode != null)
                {
                    var importedSvgElement = importedNode as SvgElement;
                    if (importedSvgElement != null)
                    {
                        importedSvgElement.Imported       = true;
                        importedSvgElement.ImportNode     = refEl as SvgElement;
                        importedSvgElement.ImportDocument = refEl.OwnerDocument as SvgDocument;
                    }

                    refEl = importedNode;
                }
            }
            else
            {
                // For elements/nodes within the same document, clone it.
                refEl = (XmlElement)refEl.CloneNode(true);
            }
            // Reset any ID on the cloned/copied element to avoid duplication of IDs.
            //           refEl.SetAttribute("id", "");

            useElement.OwnerDocument.Static = true;
            useElement.CopyToReferencedElement(refEl);

            XmlElement refSiblingEl = null;
            string     useId        = null;

            // Compensate for the parent's class and sibling css loss from cloning...
            if (refElParent != null && refElParent.HasAttribute("class"))
            {
                var parentClass = refElParent.GetAttribute("class");
                if (!string.IsNullOrWhiteSpace(parentClass))
                {
                    var parentEl = document.CreateElement(refElParent.LocalName);
                    parentEl.SetAttribute("class", parentClass);

                    parentEl.AppendChild(refEl);

                    refEl = parentEl;
                }
            }
            else if (refElParent != null && siblingNode != null)
            {
                var siblingEl = siblingNode as XmlElement;
                if (siblingEl != null && siblingEl.HasAttribute("class"))
                {
                    var siblingClass = siblingEl.GetAttribute("class");
                    if (!string.IsNullOrWhiteSpace(siblingClass))
                    {
                        refSiblingEl = (XmlElement)siblingEl.CloneNode(true);

                        useElement.AppendChild(refSiblingEl);
                    }
                }
            }
            else
            {
                //useId = useElement.Id;
                //useElement.SetAttribute("id", "");
            }

            useElement.AppendChild(refEl);

            // Now, render the use element...
            this.RenderElement(svgElement);

            if (refSiblingEl != null)
            {
                useElement.RemoveChild(refSiblingEl);
            }
            useElement.RemoveChild(refEl);
            useElement.RestoreReferencedElement(refEl);

            if (useId != null)
            {
                useElement.SetAttribute("id", useId);
            }

            this.EndUseElement(useElement, hashCode);
        }