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; }
public override PageElement VisitUseElement(SvgUseElement element) { if (element.IsRenderingDisabled || string.IsNullOrEmpty(element.Href)) { return(null); } var tx = element.X?.Value ?? 0; var ty = element.Y?.Value ?? 0; var transform = SvgMatrix.CreateTranslate(tx, ty); PushMatrix(transform); PushTransformsMatrix(element.Transform); PageElement result; var generated = element.GeneratedElement; if (generated is SvgSymbolElement symbol) { var viewportWidth = element.Width?.Value ?? 0; var viewportHeight = element.Height?.Value ?? 0; result = EstablishViewportThen(symbol, viewportWidth, viewportHeight, s => TransformAndVisitElements(s.Transform, s.Children), symbol); } else { result = generated.Accept(this); } PopTransformsMatrix(element.Transform); PopMatrix(); return(result); }
private bool BeginUseElement(SvgUseElement element, out int hashCode) { hashCode = -1; string useId = element.Id; if (string.IsNullOrWhiteSpace(useId)) { hashCode = element.OuterXml.GetHashCode(); if (_useElements.Contains(hashCode)) { return(false); } _useElements.Add(hashCode); } else { if (_useIdElements.Contains(useId)) { return(false); } _useIdElements.Add(useId); } return(true); }
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); }
public void TestInternalReference() { SvgUseElement elm = Util.GetXmlElement("<use xlink:href='#foo' /><rect id='foo' width='100' height='100' />", "", "use") as SvgUseElement; SvgRectElement rect = elm.OwnerDocument.SelectSingleNode("//*[@id='foo']") as SvgRectElement; Assert.IsNotNull(elm.InstanceRoot); Assert.AreEqual(elm, elm.InstanceRoot.CorrespondingUseElement); Assert.AreEqual(rect, elm.InstanceRoot.CorrespondingElement); }
public void TestXYWidthHeight() { SvgUseElement elm = Util.GetXmlElement("<use x='1' y='2' width='3' height='4' />", "", "use") as SvgUseElement; Assert.AreEqual(1, elm.X.AnimVal.Value); Assert.AreEqual(2, elm.Y.AnimVal.Value); Assert.AreEqual(3, elm.Width.AnimVal.Value); Assert.AreEqual(4, elm.Height.AnimVal.Value); }
private bool BeginUseElement(SvgUseElement element, out int hashCode) { hashCode = -1; if (element.Href != null && !string.IsNullOrWhiteSpace(element.Href.AnimVal)) { var hrefVal = element.Href.AnimVal; int hashStart = hrefVal.IndexOf("#", StringComparison.OrdinalIgnoreCase); if (hashStart > -1) { var svgRoot = element.OwnerSvgElement; var elemId = hrefVal.Substring(hashStart + 1).Trim(); if (!string.IsNullOrWhiteSpace(elemId) && elemId.Equals(svgRoot.Id, StringComparison.OrdinalIgnoreCase)) { return(false); } } } var refUri = element.UriReference.AbsoluteUri; if (!string.IsNullOrWhiteSpace(refUri)) { var context = _renderer.Context; if (context != null && context.ContainsUrl(refUri)) { return(false); } context.AddUrl(refUri); } string useId = element.Id; if (string.IsNullOrWhiteSpace(useId)) { hashCode = element.OuterXml.GetHashCode(); if (_useElements.Contains(hashCode)) { return(false); } _useElements.Add(hashCode); } else { if (_useIdElements.Contains(useId)) { return(false); } _useIdElements.Add(useId); } return(true); }
private bool EndUseElement(SvgUseElement element, int hashCode) { bool isRemoved = _useElements.Remove(hashCode); string useId = element.Id; if (string.IsNullOrWhiteSpace(useId)) { //int hashCode = element.OuterXml.GetHashCode(); return(isRemoved); } return(_useIdElements.Remove(useId)); }
private bool BeginUseElement(SvgUseElement element) { int hashCode = element.OuterXml.GetHashCode(); if (_useElements.Contains(hashCode)) { return(false); } _useElements.Add(hashCode); return(true); }
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 bool EndUseElement(SvgUseElement element, int hashCode) { var refUri = element.UriReference.AbsoluteUri; if (!string.IsNullOrWhiteSpace(refUri)) { var context = _renderer.Context; if (context != null && context.ContainsUrl(refUri)) { context.RemoveUrl(refUri); } } bool isRemoved = _useElements.Remove(hashCode); string useId = element.Id; if (string.IsNullOrWhiteSpace(useId)) { //int hashCode = element.OuterXml.GetHashCode(); return(isRemoved); } return(_useIdElements.Remove(useId)); }
public override void BeforeRender(WpfDrawingRenderer renderer) { base.BeforeRender(renderer); WpfDrawingContext context = renderer.Context; Geometry clipGeom = this.ClipGeometry; Transform transform = this.Transform; if (transform == null && (_svgElement.FirstChild != null && _svgElement.FirstChild == _svgElement.LastChild)) { try { SvgUseElement useElement = (SvgUseElement)_svgElement; // If none of the following attribute exists, an exception is thrown... double x = useElement.X.AnimVal.Value; double y = useElement.Y.AnimVal.Value; double width = useElement.Width.AnimVal.Value; double height = useElement.Height.AnimVal.Value; if (width > 0 && height > 0) { Rect elementBounds = new Rect(x, y, width, height); // Try handling the cases of "symbol" and "svg" sources within the "use"... XmlNode childNode = _svgElement.FirstChild; string childName = childNode.Name; if (String.Equals(childName, "symbol", StringComparison.OrdinalIgnoreCase)) { SvgSymbolElement symbolElement = (SvgSymbolElement)childNode; this.FitToViewbox(context, symbolElement, elementBounds); } } transform = this.Transform; } catch { } } if (transform != null) { try { SvgUseElement useElement = (SvgUseElement)_svgElement; // If none of the following attribute exists, an exception is thrown... double x = useElement.X.AnimVal.Value; double y = useElement.Y.AnimVal.Value; double width = useElement.Width.AnimVal.Value; double height = useElement.Height.AnimVal.Value; if (width > 0 && height > 0) { Rect elementBounds = new Rect(x, y, width, height); // Try handling the cases of "symbol" and "svg" sources within the "use"... XmlNode childNode = _svgElement.FirstChild; string childName = childNode.Name; if (String.Equals(childName, "symbol", StringComparison.OrdinalIgnoreCase)) { SvgSymbolElement symbolElement = (SvgSymbolElement)childNode; this.FitToViewbox(context, symbolElement, elementBounds); } } Transform symbolTransform = this.Transform; if (symbolTransform != null && !symbolTransform.Value.IsIdentity) { TransformGroup combinedTransform = new TransformGroup(); combinedTransform.Children.Add(transform); combinedTransform.Children.Add(symbolTransform); transform = combinedTransform; } } catch { } } if (clipGeom != null || transform != null) { _drawGroup = new DrawingGroup(); DrawingGroup currentGroup = context.Peek(); if (currentGroup == null) { throw new InvalidOperationException("An existing group is expected."); } currentGroup.Children.Add(_drawGroup); context.Push(_drawGroup); if (clipGeom != null) { _drawGroup.ClipGeometry = clipGeom; } if (transform != null) { _drawGroup.Transform = transform; } } }
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); }
public virtual void VisitUseElement(SvgUseElement element) => DefaultVisit(element);
public override SvgElement VisitUseElement(SvgUseElement element) { return(base.VisitUseElement(element)); }
private SvgRectF GetElementBounds(SvgTransformableElement element, float margin) { SvgRenderingHint hint = element.RenderingHint; if (hint == SvgRenderingHint.Shape || hint == SvgRenderingHint.Text) { GraphicsPath gp = GdiRendering.CreatePath(element); ISvgMatrix svgMatrix = element.GetScreenCTM(); Matrix matrix = new Matrix((float)svgMatrix.A, (float)svgMatrix.B, (float)svgMatrix.C, (float)svgMatrix.D, (float)svgMatrix.E, (float)svgMatrix.F); SvgRectF bounds = SvgConverter.ToRect(gp.GetBounds(matrix)); bounds = SvgRectF.Inflate(bounds, margin, margin); return(bounds); } SvgUseElement useElement = element as SvgUseElement; if (useElement != null) { SvgTransformableElement refEl = useElement.ReferencedElement as SvgTransformableElement; if (refEl == null) { return(SvgRectF.Empty); } XmlElement refElParent = (XmlElement)refEl.ParentNode; element.OwnerDocument.Static = true; useElement.CopyToReferencedElement(refEl); element.AppendChild(refEl); SvgRectF bbox = this.GetElementBounds(refEl, margin); element.RemoveChild(refEl); useElement.RestoreReferencedElement(refEl); refElParent.AppendChild(refEl); element.OwnerDocument.Static = false; return(bbox); } SvgRectF union = SvgRectF.Empty; SvgTransformableElement transformChild; foreach (XmlNode childNode in element.ChildNodes) { if (childNode is SvgDefsElement) { continue; } if (childNode is ISvgTransformable) { transformChild = (SvgTransformableElement)childNode; SvgRectF bbox = this.GetElementBounds(transformChild, margin); if (bbox != SvgRectF.Empty) { if (union == SvgRectF.Empty) { union = bbox; } else { union = SvgRectF.Union(union, bbox); } } } } return(union); }
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 bool EndUseElement(SvgUseElement element) { int hashCode = element.OuterXml.GetHashCode(); return(_useElements.Remove(hashCode)); }
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; }
public override void BeforeRender(WpfDrawingRenderer renderer) { base.BeforeRender(renderer); WpfDrawingContext context = renderer.Context; Geometry clipGeom = this.ClipGeometry; Transform transform = this.Transform; SvgUseElement useElement = (SvgUseElement)_svgElement; string elementId = this.GetElementName(); float opacityValue = -1; string opacity = useElement.GetAttribute("opacity"); if (string.IsNullOrWhiteSpace(opacity)) { opacity = useElement.GetPropertyValue("opacity"); } if (!string.IsNullOrWhiteSpace(opacity)) { opacityValue = (float)SvgNumber.ParseNumber(opacity); opacityValue = Math.Min(opacityValue, 1); opacityValue = Math.Max(opacityValue, 0); } _drawGroup = new DrawingGroup(); DrawingGroup currentGroup = context.Peek(); if (currentGroup == null) { throw new InvalidOperationException("An existing group is expected."); } currentGroup.Children.Add(_drawGroup); context.Push(_drawGroup); if (clipGeom != null || transform != null || (opacityValue >= 0 && opacityValue < 1) || (!string.IsNullOrWhiteSpace(elementId) && !context.IsRegisteredId(elementId))) { if (clipGeom != null) { _drawGroup.ClipGeometry = clipGeom; } if (transform != null) { _drawGroup.Transform = transform; } if (opacityValue >= 0 && opacityValue < 1) { _drawGroup.Opacity = opacityValue; } if (!string.IsNullOrWhiteSpace(elementId) && !context.IsRegisteredId(elementId)) { SvgObject.SetName(_drawGroup, elementId); context.RegisterId(elementId); if (context.IncludeRuntime) { SvgObject.SetId(_drawGroup, elementId); } } } }