/// <summary> /// Gets the <see cref="GraphicsPath"/> for this element. /// </summary> /// <value></value> public override GraphicsPath Path(ISvgRenderer renderer) { //if there is a TSpan inside of this text element then path should not be null (even if this text is empty!) var nodes = GetContentNodes().Where(x => x is SvgContentNode && string.IsNullOrEmpty(x.Content.Trim(new[] { '\r', '\n', '\t' }))); if (_path == null || IsPathDirty || nodes.Count() == 1) { renderer = (renderer ?? SvgRenderer.FromNull()); SetPath(new TextDrawingState(renderer, this)); } return(_path); }
/// <summary> /// Gets the <see cref="GraphicsPath"/> for this element. /// </summary> /// <value></value> public override System.Drawing.Drawing2D.GraphicsPath Path(SvgRenderer renderer) { // Make sure the path is always null if there is no text //if there is a TSpan inside of this text element then path should not be null (even if this text is empty!) if ((string.IsNullOrEmpty(this.Text) || this.Text.Trim().Length < 1) && this.Children.Where(x => x is SvgTextSpan).Select(x => x as SvgTextSpan).Count() == 0) { return(_path = null); } //NOT SURE WHAT THIS IS ABOUT - Path gets created again anyway - WTF? // When an empty string is passed to GraphicsPath, it rises an InvalidArgumentException... if (_path == null || this.IsPathDirty) { renderer = (renderer ?? SvgRenderer.FromNull()); // Measure the overall bounds of all the text var boundsData = GetTextBounds(renderer); var font = GetFont(renderer); SvgTextBase innerText; float x = (_x.Count < 1 ? _calcX : _x[0].ToDeviceValue(renderer, UnitRenderingType.HorizontalOffset, this)) + (_dx.Count < 1 ? 0 : _dx[0].ToDeviceValue(renderer, UnitRenderingType.Horizontal, this)); float y = (_y.Count < 1 ? _calcY : _y[0].ToDeviceValue(renderer, UnitRenderingType.VerticalOffset, this)) + (_dy.Count < 1 ? 0 : _dy[0].ToDeviceValue(renderer, UnitRenderingType.Vertical, this)); _path = new GraphicsPath(); _path.StartFigure(); // Determine the location of the start point switch (this.TextAnchor) { case SvgTextAnchor.Middle: x -= (boundsData.Bounds.Width / 2); break; case SvgTextAnchor.End: x -= boundsData.Bounds.Width; break; } try { renderer.Boundable(new FontBoundable(font)); switch (this.BaselineShift) { case null: case "": case "baseline": case "inherit": // do nothing break; case "sub": y += new SvgUnit(SvgUnitType.Ex, 1).ToDeviceValue(renderer, UnitRenderingType.Vertical, this); break; case "super": y -= new SvgUnit(SvgUnitType.Ex, 1).ToDeviceValue(renderer, UnitRenderingType.Vertical, this); break; default: var convert = new SvgUnitConverter(); var shift = (SvgUnit)convert.ConvertFromInvariantString(this.BaselineShift); y -= shift.ToDeviceValue(renderer, UnitRenderingType.Vertical, this); break; } } finally { renderer.PopBoundable(); } NodeBounds data; var yCummOffset = 0.0f; for (var i = 0; i < boundsData.Nodes.Count; i++) { data = boundsData.Nodes[i]; innerText = data.Node as SvgTextBase; if (innerText == null) { // Minus FontSize because the x/y coords mark the bottom left, not bottom top. DrawString(renderer, _path, x + data.xOffset, y - boundsData.Bounds.Height, font, PrepareText(data.Node.Content, i > 0 && boundsData.Nodes[i - 1].Node is SvgTextBase, i < boundsData.Nodes.Count - 1 && boundsData.Nodes[i + 1].Node is SvgTextBase)); } else { innerText._calcX = x + data.xOffset; innerText._calcY = y + yCummOffset; if (innerText.Dy.Count == 1) { yCummOffset += innerText.Dy[0].ToDeviceValue(renderer, UnitRenderingType.Vertical, this); } } } _path.CloseFigure(); this.IsPathDirty = false; } return(_path); }