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; }
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); }
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); }