// Methods internal Use(string prefix, string localname, string ns, SvgDocument doc) : base(prefix, localname, ns, doc) { this.x = 0f; this.y = 0f; this.width = 0f; this.height = 0f; this.graphId = null; this.refelement = null; }
public GdiMarkerRendering(SvgElement element) : base(element) { }
private void AddNodeToTree(SvgElement eleParent, SvgElement eleToAdd, SvgElement eleBefore) { if (eleToAdd == null) { return; } string sNodeName = eleToAdd.GetElementName(); string sId; sId = eleToAdd.Id; if (sId != "") { sNodeName += "_"; sNodeName += sId; //sNodeName += ")"; } TreeViewItem node = new TreeViewItem { Name = sNodeName }; node.Tag = eleToAdd.GetInternalId(); TreeViewItem nodeParent = null; TreeViewItem nodeBefore = null; if (eleParent != null) { nodeParent = FindNodeByTag(null, eleParent.GetInternalId().ToString()); } if (eleBefore != null) { nodeBefore = FindNodeByTag(nodeParent, eleBefore.GetInternalId().ToString()); } if (nodeParent == null) { if (nodeBefore == null) { TreeViewPrintFile.Items.Add(node); } else { //TreeViewPrintFile.Items.Insert(nodeBefore.Index, node); } } else { if (nodeBefore == null) { nodeParent.Items.Add(node); } else { //nodeParent.Items.Insert(nodeBefore.Index, node); } } //node.ImageIndex = (int)eleToAdd.getElementType(); //node.SelectedImageIndex = nod.ImageIndex; //node.Expand(); if (eleToAdd.GetChild() != null) { AddNodeToTree(eleToAdd, eleToAdd.GetChild(), null); SvgElement nxt = eleToAdd.GetChild().GetNext(); while (nxt != null) { AddNodeToTree(eleToAdd, nxt, null); nxt = nxt.GetNext(); } } TreeViewPrintFile.Items.MoveCurrentTo(node); }
public override void DefaultVisit(SvgElement element) => VisitChildren(element);
internal SvgStopElementList(SvgElement parent) : base(parent) { }
public GdiImageRendering(SvgElement element) : base(element) { }
/// <summary> /// Called by the underlying <see cref="SvgElement"/> when an element has been added to the /// 'Children' collection. /// </summary> /// <param name="child">The <see cref="SvgElement"/> that has been added.</param> /// <param name="index">An <see cref="int"/> representing the index where the element was added to the collection.</param> protected override void AddElement(SvgElement child, int index) { base.AddElement(child, index); IsPathDirty = true; }
public SvgUriReference(SvgElement target) { _href = "#" + target.Id; if (target.Id == "") { throw new SvgException("Uri Reference cannot refer to an element with no id.", target.ToString()); } }
Matrix ParseTransform(SvgElement element, Matrix parent) { return(ParseTransform(element, parent, "transform")); }
private void ClickMe(IEvent e) { SvgElement el = ((SvgElement)e.Target); MessageBox.Show("Clicked - " + el.LocalName); }
private void RenderElement(ISvgElement svgElement) { bool isNotRenderable = !svgElement.IsRenderable || string.Equals(svgElement.LocalName, "a"); if (isNotRenderable) { return; } SvgElement currentElement = (SvgElement)svgElement; GdiRenderingBase renderingNode = GdiRendering.Create(currentElement); if (renderingNode == null) { return; } if (!renderingNode.NeedRender(_renderer)) { renderingNode.Dispose(); renderingNode = null; return; } var comparer = StringComparison.OrdinalIgnoreCase; bool shouldRender = true; SvgStyleableElement stylable = svgElement as SvgStyleableElement; if (stylable != null) { string sVisibility = stylable.GetPropertyValue(CssConstants.PropVisibility); string sDisplay = stylable.GetPropertyValue(CssConstants.PropDisplay); if (string.Equals(sVisibility, CssConstants.ValHidden, comparer) || string.Equals(sDisplay, CssConstants.ValNone, comparer)) { shouldRender = false; } } if (shouldRender) { //_rendererMap[svgElement] = renderingNode; // _rendererMap.Push(renderingNode); if (_rendererMap.ContainsKey(currentElement.UniqueId)) { // Might be circular rendering... // System.Diagnostics.Debug.WriteLine("Circular Object: " + currentElement.LocalName); return; } _rendererMap[currentElement.UniqueId] = renderingNode; renderingNode.BeforeRender(_renderer); renderingNode.Render(_renderer); if (!renderingNode.IsRecursive && svgElement.HasChildNodes) { RenderChildren(svgElement); } //renderingNode = _rendererMap[svgElement]; renderingNode = _rendererMap[currentElement.UniqueId]; // renderingNode = _rendererMap.Pop(); Debug.Assert(renderingNode.Element == svgElement); renderingNode.AfterRender(_renderer); _rendererMap.Remove(currentElement.UniqueId); //_rendererMap.Remove(svgElement); } renderingNode.Dispose(); renderingNode = null; }
public void WriteToElement(SvgElement el) { if (_href != null) el["xlink:href"] = _href; if (_role != null) el["xlink:role"] = _role; if (_arcrole != null) el["xlink:arcrole"] = _arcrole; if (_title != null) el["xlink:title"] = _title; if (_show != null) el["xlink:show"] = _show; }
public void ReadFromElement(SvgElement el) { _href = (string)el["xlink:href"]; _role = (string)el["xlink:role"]; _arcrole = (string)el["xlink:arcrole"]; _title = (string)el["xlink:title"]; _show = (string)el["xlink:show"]; //ignore the possibility of setting type and actuate for now }
public SvgXRef(SvgElement el) { ReadFromElement(el); }
protected override void DeepCopy(SvgElement element) { var casted = (SvgClipPathElement)element; casted._stylableHelper = this._stylableHelper.DeepCopy(casted); }
public WpfPathRendering(SvgElement element) : base(element) { }
public static Document Get(Stream input) { SvgDocument doc; using (var wrapper = new SvgStreamWrapper(input)) doc = SvgDocument.Open <SvgDocument>(wrapper.SvgStream); var vpw = 0; var vph = 0; var ppi = doc.Ppi; if (!doc.Width.IsNone && !doc.Width.IsEmpty) { vpw = ConvertToPixels(doc.Width.Type, doc.Width.Value, doc.Ppi); } if (!doc.Height.IsNone && !doc.Height.IsEmpty) { vph = ConvertToPixels(doc.Height.Type, doc.Height.Value, doc.Ppi); } var vbx = (int)doc.ViewBox.MinX; var vby = (int)doc.ViewBox.MinY; var vbw = (int)doc.ViewBox.Width; var vbh = (int)doc.ViewBox.Height; // Store opacity as layer options. var setOpacityForLayer = true; var importHiddenLayers = true; var importGroupBoundariesAsLayers = false; var dr = DialogResult.Cancel; Document results = null; using (var dialog = new UiDialog()) { var tokenSource = new CancellationTokenSource(); var token = tokenSource.Token; dialog.FormClosing += (o, e) => { tokenSource.Cancel(); }; dialog.OkClick += (o, e) => { var canvasw = dialog.CanvasW; var canvash = dialog.CanvasH; var resolution = dialog.Dpi; var layersMode = dialog.LayerMode; var keepAspectRatio = dialog.KeepAspectRatio; setOpacityForLayer = dialog.ImportOpacity; importHiddenLayers = dialog.ImportHiddenLayers; importGroupBoundariesAsLayers = dialog.ImportGroupBoundariesAsLayers; doc.Ppi = resolution; doc.Width = new SvgUnit(SvgUnitType.Pixel, canvasw); doc.Height = new SvgUnit(SvgUnitType.Pixel, canvash); doc.AspectRatio = keepAspectRatio ? new SvgAspectRatio(SvgPreserveAspectRatio.xMinYMin) : new SvgAspectRatio(SvgPreserveAspectRatio.none); var progressCallback = new System.Action <int>(p => dialog.ReportProgress(p)); // Run in another thread and unblock the UI. // Cannot run .AsParallel().AsOrdered() to render each element in async thread while gdi+ svg renderer failing with errors... Task.Run((Action)(() => { if (layersMode == LayersMode.Flat) { // Render one flat image and quit. var bmp = RenderImage(doc, canvasw, canvash); results = Document.FromImage(bmp); } else { List <SvgVisualElement> allElements = null; allElements = PrepareFlatElements(doc.Children).Where(p => p is SvgVisualElement).Cast <SvgVisualElement>().ToList(); Document outputDocument = new Document(canvasw, canvash); if (layersMode == LayersMode.All) { // Dont render groups and boundaries if defined allElements = allElements.Where(p => !(p is SvgGroup)).ToList(); // Filter out group boundaries if not set. if (!importGroupBoundariesAsLayers) { allElements = allElements.Where(p => !(p is PaintGroupBoundaries)).ToList(); } // Thread safe dialog.SetMaxProgress(allElements.Count + 10); dialog.ReportProgress(10); RenderElements(allElements, outputDocument, setOpacityForLayer, importHiddenLayers, progressCallback, token); } else if (layersMode == LayersMode.Groups) { // Get only parent groups and single elements var groupsAndElementsWithoutGroup = new List <SvgVisualElement>(); foreach (var element in allElements) { if (element is PaintGroupBoundaries) { continue; } if (element.ContainsAttribute(groupAttribute)) { // Get only root level SvgGroup lastGroup = null; if (element is SvgGroup) { lastGroup = (SvgGroup)element; } SvgElement toCheck = element; while (toCheck != null) { toCheck = toCheck.Parent; if (toCheck is SvgGroup) { // TODO: render more groups. In most cases svg has only few root groups. var groupToCheck = (SvgGroup)toCheck; var title = GetLayerTitle(groupToCheck); if (!string.IsNullOrEmpty(title)) { lastGroup = groupToCheck; } } } if (!groupsAndElementsWithoutGroup.Contains(lastGroup)) { groupsAndElementsWithoutGroup.Add(lastGroup); } } else { groupsAndElementsWithoutGroup.Add(element); } } // Thread safe dialog.SetMaxProgress(groupsAndElementsWithoutGroup.Count + 10); dialog.ReportProgress(10); RenderElements(groupsAndElementsWithoutGroup, outputDocument, setOpacityForLayer, importHiddenLayers, progressCallback, token); } // Fallback. Nothing is added. Render one default layer. if (outputDocument.Layers.Count == 0) { var bmp = RenderImage(doc, canvasw, canvash); outputDocument = Document.FromImage(bmp); } results = outputDocument; } }), token) .ContinueWith((p) => { if (p.Exception != null && !p.IsCanceled) { if (p.Exception.InnerExceptions != null && p.Exception.InnerExceptions.Any(exception => exception is OutOfMemoryException)) { MessageBox.Show("Not enought memory to complete this operation."); } else { var innerExpection = p.Exception?.InnerException?.Message; MessageBox.Show(p.Exception.Message + ". Message:" + innerExpection); } dialog.DialogResult = DialogResult.Cancel; } else { if (dialog.DialogResult == DialogResult.None) { dialog.DialogResult = DialogResult.OK; } } }); }; Form mainForm = GetMainForm(); if (mainForm != null) { mainForm.Invoke((MethodInvoker)(() => { dialog.SetSvgInfo(vpw, vph, vbx, vby, vbw, vbh, ppi); dr = dialog.ShowDialog(mainForm); })); } else { dialog.SetSvgInfo(vpw, vph, vbx, vby, vbw, vbh, ppi); dr = dialog.ShowDialog(); } if (dr != DialogResult.OK) { throw new OperationCanceledException("Cancelled by user"); } return(results); } }
static Expression CreateFloat(SvgElement element, string attribute) { var value = ParseFloat(element, attribute); return(Expression.Constant(value, typeof(float))); }
private void DrawImagePixel(SvgElement container, Color c, float x, float y, float w, float h) { if (c.A == 0) return; SvgRectElement rc = new SvgRectElement(x, y, w, h); rc.Id=""; rc.Style.Set("fill", "rgb("+c.R+","+c.G+","+c.B+")"); if (c.A < 255) rc.Style.Set("opacity", c.A/255f); container.AddChild(rc); }
Expression CreateTransform(SvgElement element, Matrix parent) { var transform = ParseTransform(element, parent); return(transform != null?Expression.Constant(transform) : null); }
/// <summary> /// Called by the underlying <see cref="SvgElement"/> when an element has been removed from the /// <see cref="SvgElement.Children"/> collection. /// </summary> /// <param name="child">The <see cref="SvgElement"/> that has been removed.</param> protected override void RemoveElement(SvgElement child) { base.RemoveElement(child); IsPathDirty = true; }
static float ParseFloat(SvgElement element, string attribute) { return(float.Parse((string)element.Attributes[attribute], CultureInfo.InvariantCulture)); }
public GdiTextRendering(SvgElement element) : base(element) { _textMode = GdiTextMode.Rendering; }
public abstract string Visit(SvgElement element, WpfDrawingContext context);
public virtual void DefaultVisit(SvgElement element) { // nop }
private void ProcessMouseEvents(string type, MouseEventArgs e) { //Color pixel = _idMapRaster.GetPixel(e.X, e.Y); //SvgElement svgElement = GetElementFromColor(pixel); SvgElement svgElement = null; var hitTestResult = _hitTestHelper.HitTest(e.X, e.Y); if (hitTestResult != null) { svgElement = hitTestResult.Element; } if (type == "mouseup") { type = type.Trim(); } if (svgElement == null) { // jr patch if (_currentTarget != null && type == "mousemove") { _currentTarget.DispatchEvent(new MouseEvent(EventType.MouseOut, true, false, null, // todo: put view here 0, // todo: put detail here e.X, e.Y, e.X, e.Y, false, false, false, false, 0, null, false)); } _currentTarget = null; return; } IEventTarget target; if (svgElement.ElementInstance != null) { target = svgElement.ElementInstance as IEventTarget; } else { target = svgElement as IEventTarget; } if (target == null) { // jr patch if (_currentTarget != null && type == "mousemove") { _currentTarget.DispatchEvent(new MouseEvent(EventType.MouseOut, true, false, null, // todo: put view here 0, // todo: put detail here e.X, e.Y, e.X, e.Y, false, false, false, false, 0, null, false)); } _currentTarget = null; return; } switch (type) { case "mousemove": { if (_currentTarget == target) { target.DispatchEvent(new MouseEvent(EventType.MouseMove, true, false, null, // todo: put view here 0, // todo: put detail here e.X, e.Y, e.X, e.Y, false, false, false, false, 0, null, false)); } else { if (_currentTarget != null) { _currentTarget.DispatchEvent(new MouseEvent(EventType.MouseOut, true, false, null, // todo: put view here 0, // todo: put detail here e.X, e.Y, e.X, e.Y, false, false, false, false, 0, null, false)); } target.DispatchEvent(new MouseEvent(EventType.MouseOver, true, false, null, // todo: put view here 0, // todo: put detail here e.X, e.Y, e.X, e.Y, false, false, false, false, 0, null, false)); } break; } case "mousedown": target.DispatchEvent(new MouseEvent(EventType.MouseDown, true, false, null, // todo: put view here 0, // todo: put detail here e.X, e.Y, e.X, e.Y, false, false, false, false, 0, null, false)); _currentDownTarget = target; _currentDownX = e.X; _currentDownY = e.Y; break; case "mouseup": target.DispatchEvent(new MouseEvent(EventType.MouseUp, true, false, null, // todo: put view here 0, // todo: put detail here e.X, e.Y, e.X, e.Y, false, false, false, false, 0, null, false)); if (Math.Abs(_currentDownX - e.X) < 5 && Math.Abs(_currentDownY - e.Y) < 5) { target.DispatchEvent(new MouseEvent(EventType.Click, true, false, null, // todo: put view here 0, // todo: put detail here e.X, e.Y, e.X, e.Y, false, false, false, false, 0, null, false)); } _currentDownTarget = null; _currentDownX = 0; _currentDownY = 0; break; } _currentTarget = target; }
public virtual void Visit(SvgElement element) => element?.Accept(this);
protected WpfRenderingBase(SvgElement element) { this._svgElement = element; }
public WpfPatternRendering(SvgElement element) : base(element) { //_isRoot = false; _isRecursive = false; }
public override void Draw(Graphics g, int time) { int num1 = 0; int num2 = 0; AnimFunc.CreateAnimateValues(this, time, out num1, out num2); GraphicsContainer container1 = g.BeginContainer(); g.SmoothingMode = base.OwnerDocument.SmoothingMode; g.TextRenderingHint = base.OwnerDocument.TextRenderingHint; ISvgBrush brush1 = base.GraphBrush; float single1 = base.Size; this.GPath = new GraphicsPath(); GraphicsPath path1 = new GraphicsPath(); StringFormat format1 = base.GetGDIStringFormat(); FontFamily family1 = base.GetGDIFontFamily(); this.currentPostion.X += (base.X + base.Dx); this.currentPostion.Y += (base.Y + base.Dy); SvgElement element1 = this.RefElement; string text1 = string.Empty; if (element1 is Text) { text1 = base.TrimText(element1.FirstChild.Value); } if (text1 != string.Empty) { float single2 = 0f; if (format1.Alignment == StringAlignment.Near) { single2 = (single1 * 1f) / 6f; } else if (format1.Alignment == StringAlignment.Far) { single2 = (-single1 * 1f) / 6f; } float single3 = (((float)family1.GetCellAscent(FontStyle.Regular)) / ((float)family1.GetEmHeight(FontStyle.Regular))) * single1; if (text1 != null) { path1.AddString(text1, family1, base.GetGDIStyle(), single1, new PointF(this.currentPostion.X - single2, this.currentPostion.Y - single3), format1); } this.currentPostion.X -= single2; RectangleF ef1 = path1.GetBounds(); if (!ef1.IsEmpty) { RectangleF ef2 = path1.GetBounds(); float single4 = ef2.Width; if (format1.Alignment == StringAlignment.Center) { single4 /= 2f; } else if (format1.Alignment == StringAlignment.Far) { single4 = 0f; } this.currentPostion.X += (single4 + (single1 / 4f)); } brush1.Paint(path1, g, time); // Stroke stroke1 = Stroke.GetStroke(this); base.GraphStroke.Paint(g, this, path1, time); this.GPath.StartFigure(); this.GPath.AddPath(path1, false); } g.EndContainer(container1); }
static void LoadSvgDataIntoScriptable(SvgScriptable svgObj, XmlNode node) { foreach (XmlNode childNode in node.ChildNodes) { if (!(childNode is XmlElement)) { continue; } var xmlElement = childNode as XmlElement; // if group, flatten it if (xmlElement.Name == "g") { LoadSvgDataIntoScriptable(svgObj, childNode); continue; } SvgElement svgElement = new SvgElement(); LoadFillAndStrode(svgElement, xmlElement); switch (xmlElement.Name) { case "line": { svgElement.Points = ExtractLinePoints(xmlElement).ToList(); break; } case "polyline": { svgElement.Points = ExtractPolyPoints(xmlElement).ToList(); break; } case "polygon": { svgElement.Points = ExtractPolyPoints(xmlElement).ToList(); svgElement.IsClosed = true; break; } case "path": { svgElement.Points = ExtractPathPoints(xmlElement).ToList(); if (xmlElement.GetAttribute("d").ToLower().Trim().Last() == 'z') { svgElement.IsClosed = true; } break; } case "rect": { svgElement.Points = ExtractRectPoints(xmlElement).ToList(); svgElement.IsClosed = true; break; } } RemoveRepeatedPoints(svgElement); if (svgElement.Points.Count <= 1) { continue; } CheckForClosedElement(svgElement); //matrix mult if (xmlElement.HasAttribute("transform")) { var mtxStr = xmlElement.GetAttribute("transform"); if (mtxStr.StartsWith("matrix")) { mtxStr = mtxStr.Substring(7, mtxStr.Length - 8); var coords = mtxStr.Split().Select(p => float.Parse(p)).ToArray(); for (int ptInx = 0; ptInx < svgElement.Points.Count; ptInx++) { var oldPt = svgElement.Points[ptInx]; var newX = coords[0] * oldPt.x + coords[2] * oldPt.y + coords[4]; var newY = coords[1] * oldPt.x + coords[3] * oldPt.y + coords[5]; svgElement.Points[ptInx] = new Vector2(newX, newY); } } } svgObj.SvgData.Add(svgElement); } }
public GdiRendering(SvgElement element) : base(element) { _uniqueColor = Color.Empty; }
/// <summary> /// Get a title for a specified svg element. /// </summary> private static string GetLayerTitle(SvgElement element) { var layerName = element.ID; if (element.CustomAttributes != null) { // get custom title attributes. foreach (var titleAttribute in allowedTitles) { string title; if (element.CustomAttributes.TryGetValue(titleAttribute, out title)) { if (!string.IsNullOrEmpty(title)) { layerName = title; return(layerName); } } } // Get child title tag if (element.Children != null) { var title = element.Children.FirstOrDefault(p => p is SvgTitle); if (title != null && !string.IsNullOrEmpty(title.Content)) { layerName = title.Content; return(layerName); } } } if (string.IsNullOrEmpty(layerName)) { var prop = typeof(SvgElement).GetProperty("ElementName", BindingFlags.NonPublic | BindingFlags.Instance); if (prop != null) { var getter = prop.GetGetMethod(nonPublic: true); layerName = getter.Invoke(element, null) as string; } if (string.IsNullOrEmpty(layerName)) { layerName = element.GetType().Name; } // Generate more meanfull name for a svg use node. Add reference element name in a case if it's local document. var useElement = element as SvgUse; if (useElement != null && useElement.ReferencedElement != null && !string.IsNullOrEmpty(useElement.ReferencedElement.OriginalString)) { var str = useElement.ReferencedElement.OriginalString.Trim(); if (str.StartsWith("#")) { layerName += str.Replace('#', ' '); } } // Genearte more meanfull name for a svg text. var text = element as SvgTextBase; if (text != null && !string.IsNullOrEmpty(text.Text)) { var textToUse = text.Text; if (text.Text.Length > 35) { textToUse = text.Text.Substring(0, 35); } layerName += " " + textToUse; } } return(layerName); }
protected override void Initialize(SvgElement element) { base.Initialize(element); _drawGroup = null; }
protected void FitToViewbox(WpfDrawingContext context, SvgElement svgElement, Rect elementBounds) { if (svgElement == null) { return; } ISvgFitToViewBox fitToView = svgElement as ISvgFitToViewBox; if (fitToView == null) { return; } SvgPreserveAspectRatio spar = (SvgPreserveAspectRatio)fitToView.PreserveAspectRatio.AnimVal; SvgRect viewBox = (SvgRect)fitToView.ViewBox.AnimVal; SvgRect rectToFit = new SvgRect(elementBounds.X, elementBounds.Y, elementBounds.Width, elementBounds.Height); double[] transformArray = spar.FitToViewBox(viewBox, rectToFit); double translateX = Math.Round(transformArray[0], 4); double translateY = Math.Round(transformArray[1], 4); double scaleX = Math.Round(transformArray[2], 4); double scaleY = Math.Round(transformArray[3], 4); Transform translateMatrix = null; Transform scaleMatrix = null; if (!translateX.Equals(0.0) || !translateY.Equals(0.0)) { translateMatrix = new TranslateTransform(translateX, translateY); } if (!scaleX.Equals(1.0) || !scaleY.Equals(1.0)) { scaleMatrix = new ScaleTransform(scaleX, scaleY); } if (translateMatrix != null && scaleMatrix != null) { // Create a TransformGroup to contain the transforms // and add the transforms to it. if (translateMatrix.Value.IsIdentity && scaleMatrix.Value.IsIdentity) { return; } if (translateMatrix.Value.IsIdentity) { this.Transform = scaleMatrix; return; } if (scaleMatrix.Value.IsIdentity) { this.Transform = translateMatrix; return; } TransformGroup transformGroup = new TransformGroup(); transformGroup.Children.Add(scaleMatrix); transformGroup.Children.Add(translateMatrix); this.Transform = transformGroup; } else if (translateMatrix != null) { this.Transform = translateMatrix; } else if (scaleMatrix != null) { this.Transform = scaleMatrix; } }
public WpfGroupRendering(SvgElement element) : base(element) { }
protected override void DeepCopy(SvgElement element) { var casted = (SvgCircleElement)element; casted._stylableHelper = this._stylableHelper.DeepCopy(casted); casted._transformableHelper = this._transformableHelper.DeepCopy(); }
private void RenderTextPath(SvgTextPathElement textPath, ref Point ctp, double rotate, WpfTextPlacement placement) { if (textPath.ChildNodes == null || textPath.ChildNodes.Count == 0) { return; } SvgElement targetPath = textPath.ReferencedElement as SvgElement; if (targetPath == null) { return; } Geometry textGeometry = CreateGeometry(targetPath, true); if (textGeometry == null) { return; } PathGeometry pathGeometry = textGeometry as PathGeometry; if (pathGeometry == null) { pathGeometry = textGeometry.GetFlattenedPathGeometry(); } // If the path has a transform, apply it to get a transformed path... if (targetPath.HasAttribute("transform")) { var svgTransform = new SvgTransformList(targetPath.GetAttribute("transform")); var svgMatrix = svgTransform.TotalMatrix; if (!svgMatrix.IsIdentity) { pathGeometry.Transform = new MatrixTransform(svgMatrix.A, svgMatrix.B, svgMatrix.C, svgMatrix.D, svgMatrix.E, svgMatrix.F); var transformPath = new PathGeometry(); transformPath.AddGeometry(pathGeometry); pathGeometry = transformPath; } } WpfPathTextBuilder pathBuilder = new WpfPathTextBuilder(_textElement); pathBuilder.BeginTextPath(textPath); var comparer = StringComparison.OrdinalIgnoreCase; XmlNodeType nodeType = XmlNodeType.None; int nodeCount = textPath.ChildNodes.Count; for (int i = 0; i < nodeCount; i++) { XmlNode child = textPath.ChildNodes[i]; nodeType = child.NodeType; if (nodeType == XmlNodeType.Text) { var nodeText = GetText(textPath, child); if (i == (nodeCount - 1)) { // No need to render the last white space... if (nodeCount == 1) { if (nodeText.StartsWith(NonBreaking, StringComparison.OrdinalIgnoreCase)) { if (!nodeText.EndsWith(NonBreaking, StringComparison.OrdinalIgnoreCase)) { nodeText = nodeText.TrimEnd(); } } else if (nodeText.EndsWith(NonBreaking, StringComparison.OrdinalIgnoreCase)) { nodeText = nodeText.TrimStart(); } else { nodeText = nodeText.Trim(); } } else { if (!nodeText.EndsWith(NonBreaking, StringComparison.OrdinalIgnoreCase)) { nodeText = nodeText.TrimEnd(); } } } else if (i == 0) { nodeText = nodeText.Trim(); } RenderTextPath(textPath, pathBuilder, nodeText, new Point(ctp.X, ctp.Y), rotate, placement); } else if (nodeType == XmlNodeType.Element) { string nodeName = child.Name; if (string.Equals(nodeName, "tref", comparer)) { RenderTRefPath((SvgTRefElement)child, pathBuilder, ref ctp); } else if (string.Equals(nodeName, "tspan", comparer)) { RenderTSpanPath((SvgTSpanElement)child, pathBuilder, ref ctp); } } } WpfTextStringFormat stringFormat = GetTextStringFormat(textPath); //ISvgAnimatedLength pathOffset = textPath.StartOffset; //SvgTextPathMethod pathMethod = (SvgTextPathMethod)textPath.Method.BaseVal; //SvgTextPathSpacing pathSpacing = (SvgTextPathSpacing)textPath.Spacing.BaseVal; pathBuilder.RenderTextPath(_drawContext, pathGeometry, stringFormat.Alignment); pathBuilder.EndTextPath(); }