private void RenderTSpanPath(SvgTSpanElement element, WpfPathTextBuilder pathBuilder, ref Point ctp) { WpfTextPlacement placement = WpfTextPlacement.Create(element, ctp, true); ctp = placement.Location; double rotate = placement.Rotation; if (!placement.HasPositions) { placement = null; // Render it useless. } string sBaselineShift = element.GetPropertyValue("baseline-shift").Trim(); double shiftBy = 0; var comparer = StringComparison.OrdinalIgnoreCase; if (sBaselineShift.Length > 0) { SvgTextBaseElement textElement = (SvgTextBaseElement)element.SelectSingleNode("ancestor::svg:text", element.OwnerDocument.NamespaceManager); double textFontSize = GetComputedFontSize(textElement); if (sBaselineShift.EndsWith("%", comparer)) { shiftBy = SvgNumber.ParseNumber(sBaselineShift.Substring(0, sBaselineShift.Length - 1)) / 100f * textFontSize; } else if (string.Equals(sBaselineShift, "sub", comparer)) { shiftBy = -0.6F * textFontSize; } else if (string.Equals(sBaselineShift, "super", comparer)) { shiftBy = 0.6F * textFontSize; } else if (string.Equals(sBaselineShift, "baseline", comparer)) { shiftBy = 0; } else { shiftBy = SvgNumber.ParseNumber(sBaselineShift); } } foreach (XmlNode child in element.ChildNodes) { if (child.NodeType == XmlNodeType.Text) { ctp.Y -= shiftBy; RenderTextPath(element, pathBuilder, GetText(element, child), new Point(ctp.X, ctp.Y), rotate, placement); ctp.Y += shiftBy; } } }
public WpfTextContext(SvgTextBaseElement textElement, WpfTextRendering textRendering) { if (textRendering == null) { throw new ArgumentNullException(nameof(textRendering), "The text rendering object is required, and cannot be null (or Nothing)."); } _textRendering = textRendering; this.SetElement(textElement); }
protected override void Initialize(SvgElement element) { base.Initialize(element); _isMeasuring = false; _isGroupAdded = false; _isTextPath = false; _textWidth = 0; _drawGroup = null; _textElement = element as SvgTextBaseElement; if (_textElement == null) { throw new InvalidOperationException(); } if (_textContext == null) { _textContext = new WpfTextContext(_textElement, this); } else { _textContext.SetElement(_textElement); } if (_horzRenderer == null) { _horzRenderer = new WpfHorzTextRenderer(_textElement, this); } else { _horzRenderer.Uninitialize(); _horzRenderer.SetElement(_textElement); } if (_vertRenderer == null) { _vertRenderer = new WpfVertTextRenderer(_textElement, this); } else { _vertRenderer.Uninitialize(); _vertRenderer.SetElement(_textElement); } if (_pathRenderer == null) { _pathRenderer = new WpfPathTextRenderer(_textElement, this); } else { _pathRenderer.Uninitialize(); _pathRenderer.SetElement(_textElement); } }
public WpfTextRendering(SvgElement element) : base(element) { _textElement = element as SvgTextBaseElement; if (_textElement != null) { _textContext = new WpfTextContext(_textElement, this); _horzRenderer = new WpfHorzTextRenderer(_textElement, this); _vertRenderer = new WpfVertTextRenderer(_textElement, this); _pathRenderer = new WpfPathTextRenderer(_textElement, this); } }
public WpfTextRendering(SvgElement element) : base(element) { _textElement = element as SvgTextBaseElement; if (_textElement == null) { throw new InvalidOperationException(); } _textContext = new WpfTextContext(_textElement, this); _horzRenderer = new WpfHorzTextRenderer(_textElement, this); _vertRenderer = new WpfVertTextRenderer(_textElement, this); _pathRenderer = new WpfPathTextRenderer(_textElement, this); }
protected WpfTextRenderer(SvgTextBaseElement textElement, WpfTextRendering textRendering) { if (textElement == null) { throw new ArgumentNullException(nameof(textElement), "The SVG text element is required, and cannot be null (or Nothing)."); } if (textRendering == null) { throw new ArgumentNullException(nameof(textRendering), "The text rendering object is required, and cannot be null (or Nothing)."); } _textElement = textElement; _textRendering = textRendering; }
private void AddTSpanElementPath(SvgTSpanElement element, ref PointF ctp) { ctp = GetCurrentTextPosition(element, ctp); string sBaselineShift = element.GetPropertyValue("baseline-shift").Trim(); double shiftBy = 0; if (sBaselineShift.Length > 0) { SvgTextBaseElement textElement = (SvgTextBaseElement)element.SelectSingleNode("ancestor::svg:text", element.OwnerDocument.NamespaceManager); float textFontSize = GetComputedFontSize(textElement); if (sBaselineShift.EndsWith("%", StringComparison.OrdinalIgnoreCase)) { shiftBy = SvgNumber.ParseNumber(sBaselineShift.Substring(0, sBaselineShift.Length - 1)) / 100 * textFontSize; } else if (sBaselineShift == "sub") { shiftBy = -0.6F * textFontSize; } else if (sBaselineShift == "super") { shiftBy = 0.6F * textFontSize; } else if (sBaselineShift == "baseline") { shiftBy = 0; } else { shiftBy = SvgNumber.ParseNumber(sBaselineShift); } } foreach (XmlNode child in element.ChildNodes) { if (child.NodeType == XmlNodeType.Text) { ctp.Y -= (float)shiftBy; AddGraphicsPath(element, ref ctp, GetText(element, child)); ctp.Y += (float)shiftBy; } } }
private ISvgAnimatedLength GetStartOffset(SvgTextBaseElement textElement) { ISvgAnimatedLengthList pathOffsets = null; SvgTextPositioningElement posElement = _contentElement as SvgTextPositioningElement; if (posElement == null) { pathOffsets = textElement.Dx; if (pathOffsets != null && pathOffsets.Count != 0) { return(pathOffsets[0]); } pathOffsets = textElement.X; if (pathOffsets != null && pathOffsets.Count != 0) { return(pathOffsets[0]); } return(null); } pathOffsets = posElement.Dx; if (pathOffsets != null && pathOffsets.Count != 0) { return(pathOffsets[0]); } pathOffsets = posElement.X; if (pathOffsets != null && pathOffsets.Count != 0) { return(pathOffsets[0]); } pathOffsets = textElement.Dx; if (pathOffsets != null && pathOffsets.Count != 0) { return(pathOffsets[0]); } pathOffsets = textElement.X; if (pathOffsets != null && pathOffsets.Count != 0) { return(pathOffsets[0]); } return(null); }
public void SetElement(SvgTextBaseElement textElement) { if (textElement == null) { throw new ArgumentNullException(nameof(textElement), "The SVG text element is required, and cannot be null (or Nothing)."); } _isVertical = false; _isSingleText = false; _isSingleLine = false; _isTextPath = false; _positioningStart = new Point(0, 0); _positioningEnd = new Point(0, 0); _textElement = textElement; this.Initialize(); }
private ISvgAnimatedLength GetStartOffset(SvgTextPathElement pathElement, SvgTextBaseElement textElement) { ISvgAnimatedLength pathOffset = pathElement.StartOffset; if (pathOffset != null && pathOffset.AnimVal != null) { if (pathOffset.AnimVal.Value.Equals(0)) { var curOffset = this.GetStartOffset(textElement); if (curOffset != null && curOffset.AnimVal != null) { if (!curOffset.AnimVal.Value.Equals(0)) { return(curOffset); } } } return(pathOffset); } return(this.GetStartOffset(textElement)); }
public WpfPathTextRenderer(SvgTextBaseElement textElement, WpfTextRendering textRendering) : base(textElement, textRendering) { }
public override void Render(GdiGraphicsRenderer renderer) { _graphics = renderer.GdiGraphics; //SvgRenderingHint hint = _svgElement.RenderingHint; //if (hint == SvgRenderingHint.Clipping) //{ // return; //} //if (_svgElement.ParentNode is SvgClipPathElement) //{ // return; //} SvgTextBaseElement textElement = _svgElement as SvgTextBaseElement; if (textElement == null) { return; } string sVisibility = textElement.GetPropertyValue("visibility"); string sDisplay = textElement.GetPropertyValue("display"); if (string.Equals(sVisibility, "hidden") || string.Equals(sDisplay, "none")) { return; } if (_textMode != GdiTextMode.Outlining) { SetClip(_graphics); } PointF ctp = new PointF(0, 0); // current text position ctp = GetCurrentTextPosition(textElement, ctp); string sBaselineShift = textElement.GetPropertyValue("baseline-shift").Trim(); double shiftBy = 0; if (sBaselineShift.Length > 0) { float textFontSize = GetComputedFontSize(textElement); if (sBaselineShift.EndsWith("%", StringComparison.OrdinalIgnoreCase)) { shiftBy = SvgNumber.ParseNumber(sBaselineShift.Substring(0, sBaselineShift.Length - 1)) / 100 * textFontSize; } else if (sBaselineShift == "sub") { shiftBy = -0.6F * textFontSize; } else if (sBaselineShift == "super") { shiftBy = 0.6F * textFontSize; } else if (sBaselineShift == "baseline") { shiftBy = 0; } else { shiftBy = SvgNumber.ParseNumber(sBaselineShift); } } // For for fonts loading in the background... var svgDoc = _svgElement.OwnerDocument; if (svgDoc.IsFontsLoaded == false) { //TODO: Use of SpinUntil is known to CPU heavy, but will work for now... SpinWait.SpinUntil(() => svgDoc.IsFontsLoaded == true); } XmlNodeType nodeType = XmlNodeType.None; foreach (XmlNode child in _svgElement.ChildNodes) { SvgStyleableElement stylable = child as SvgStyleableElement; if (stylable != null) { sVisibility = stylable.GetPropertyValue("visibility"); sDisplay = stylable.GetPropertyValue("display"); if (string.Equals(sVisibility, "hidden") || string.Equals(sDisplay, "none")) { continue; } } nodeType = child.NodeType; if (nodeType == XmlNodeType.Text) { ctp.Y -= (float)shiftBy; AddGraphicsPath(textElement, ref ctp, GetText(textElement, child)); ctp.Y += (float)shiftBy; } else if (nodeType == XmlNodeType.Element) { string nodeName = child.Name; if (string.Equals(nodeName, "tref")) { AddTRefElementPath((SvgTRefElement)child, ref ctp); } else if (string.Equals(nodeName, "tspan")) { AddTSpanElementPath((SvgTSpanElement)child, ref ctp); } } } PaintMarkers(renderer, textElement, _graphics); _graphics = null; }
public virtual void SetElement(SvgTextBaseElement textElement) { _drawContext = null; _context = null; _textElement = textElement; }
protected WpfTextStringFormat GetTextStringFormat(SvgTextContentElement element) { WpfTextStringFormat sf = WpfTextStringFormat.Default; bool doAlign = true; if (element is SvgTSpanElement || element is SvgTRefElement) { SvgTextPositioningElement posElement = (SvgTextPositioningElement)element; if (posElement.X.AnimVal.NumberOfItems == 0) { doAlign = false; } } var comparer = StringComparison.OrdinalIgnoreCase; string dir = element.GetPropertyValue("direction"); bool isRightToLeft = string.Equals(dir, "rtl", comparer); sf.Direction = isRightToLeft ? FlowDirection.RightToLeft : FlowDirection.LeftToRight; if (doAlign) { string anchor = element.GetPropertyValue("text-anchor"); if (isRightToLeft) { if (string.Equals(anchor, "middle", comparer)) { sf.Anchor = WpfTextAnchor.Middle; } else if (string.Equals(anchor, "end", comparer)) { sf.Anchor = WpfTextAnchor.Start; } else { sf.Anchor = WpfTextAnchor.End; } } else { if (string.Equals(anchor, "middle", comparer)) { sf.Anchor = WpfTextAnchor.Middle; } else if (string.Equals(anchor, "end", comparer)) { sf.Anchor = WpfTextAnchor.End; } } } else { SvgTextBaseElement textElement = element.ParentNode as SvgTextBaseElement; if (textElement != null) { string anchor = textElement.GetPropertyValue("text-anchor"); if (isRightToLeft) { if (string.Equals(anchor, "middle", comparer)) { sf.Anchor = WpfTextAnchor.Middle; } else if (string.Equals(anchor, "end", comparer)) { sf.Anchor = WpfTextAnchor.Start; } else { sf.Anchor = WpfTextAnchor.End; } } else { if (string.Equals(anchor, "middle", comparer)) { sf.Anchor = WpfTextAnchor.Middle; } else if (string.Equals(anchor, "end", comparer)) { sf.Anchor = WpfTextAnchor.End; } } } } //if (isRightToLeft) //{ // if (sf.Alignment == TextAlignment.Right) // sf.Alignment = TextAlignment.Left; // else if (sf.Alignment == TextAlignment.Left) // sf.Alignment = TextAlignment.Right; // //sf.FormatFlags = StringFormatFlags.DirectionRightToLeft; //} //dir = element.GetPropertyValue("writing-mode"); //if (dir == "tb") //{ // sf.FormatFlags = sf.FormatFlags | StringFormatFlags.DirectionVertical; //} //sf.FormatFlags = sf.FormatFlags | StringFormatFlags.MeasureTrailingSpaces; return(sf); }
private void RenderTextRun(WpfTextTuple textInfo, ref Point ctp, string text, double rotate, WpfTextPlacement placement) { if (string.IsNullOrWhiteSpace(text)) { return; } WpfFontFamilyInfo familyInfo = textInfo.Item1; double emSize = textInfo.Item2; WpfTextStringFormat stringFormat = textInfo.Item3; SvgTextContentElement element = textInfo.Item4; FontFamily fontFamily = familyInfo.Family; FontWeight fontWeight = familyInfo.Weight; FontStyle fontStyle = familyInfo.Style; FontStretch fontStretch = familyInfo.Stretch; WpfSvgPaint fillPaint = new WpfSvgPaint(_context, element, "fill"); Brush textBrush = fillPaint.GetBrush(); WpfSvgPaint strokePaint = new WpfSvgPaint(_context, element, "stroke"); Pen textPen = strokePaint.GetPen(); if (textBrush == null && textPen == null) { return; } if (textBrush == null) { // If here, then the pen is not null, and so the fill cannot be null. // We set this to transparent for stroke only text path... textBrush = Brushes.Transparent; } if (textPen != null) { textPen.LineJoin = PenLineJoin.Miter; // Better for text rendering textPen.MiterLimit = 1; } TextDecorationCollection textDecors = GetTextDecoration(element); if (textDecors == null) { SvgTextBaseElement textElement = element.ParentNode as SvgTextBaseElement; if (textElement != null) { textDecors = GetTextDecoration(textElement); } } TextAlignment alignment = stringFormat.Alignment; bool hasWordSpacing = false; string wordSpaceText = element.GetAttribute("word-spacing"); double wordSpacing = 0; if (!string.IsNullOrWhiteSpace(wordSpaceText) && double.TryParse(wordSpaceText, out wordSpacing) && !wordSpacing.Equals(0)) { hasWordSpacing = true; } bool hasLetterSpacing = false; string letterSpaceText = element.GetAttribute("letter-spacing"); double letterSpacing = 0; if (!string.IsNullOrWhiteSpace(letterSpaceText) && double.TryParse(letterSpaceText, out letterSpacing) && !letterSpacing.Equals(0)) { hasLetterSpacing = true; } bool isRotatePosOnly = false; IList <WpfTextPosition> textPositions = null; int textPosCount = 0; if ((placement != null && placement.HasPositions)) { textPositions = placement.Positions; textPosCount = textPositions.Count; isRotatePosOnly = placement.IsRotateOnly; } WpfTextBuilder textBuilder = WpfTextBuilder.Create(familyInfo, this.TextCulture, emSize); this.IsTextPath = true; if (textPositions != null && textPositions.Count != 0) { if (textPositions.Count == text.Trim().Length) //TODO: Best way to handle this... { text = text.Trim(); } } if (hasLetterSpacing || hasWordSpacing || textPositions != null) { double spacing = Convert.ToDouble(letterSpacing); int startSpaces = 0; for (int i = 0; i < text.Length; i++) { if (char.IsWhiteSpace(text[i])) { startSpaces++; } else { break; } } int j = 0; string inputText = string.Empty; for (int i = 0; i < text.Length; i++) { // Avoid rendering only spaces at the start of text run... if (i == 0 && startSpaces != 0) { inputText = text.Substring(0, startSpaces + 1); i += startSpaces; } else { inputText = new string(text[i], 1); } if (this.IsMeasuring) { var textSize = textBuilder.MeasureText(element, inputText); this.AddTextWidth(ctp, textSize.Width); continue; } textBuilder.Trimming = stringFormat.Trimming; textBuilder.TextAlignment = stringFormat.Alignment; if (textDecors != null && textDecors.Count != 0) { textBuilder.TextDecorations = textDecors; } WpfTextPosition?textPosition = null; if (textPositions != null && j < textPosCount) { textPosition = textPositions[j]; } //float xCorrection = 0; //if (alignment == TextAlignment.Left) // xCorrection = emSize * 1f / 6f; //else if (alignment == TextAlignment.Right) // xCorrection = -emSize * 1f / 6f; double yCorrection = textBuilder.Baseline; float rotateAngle = (float)rotate; if (textPosition != null) { if (!isRotatePosOnly) { Point pt = textPosition.Value.Location; ctp.X = pt.X; ctp.Y = pt.Y; } rotateAngle = (float)textPosition.Value.Rotation; } Point textStart = ctp; RotateTransform rotateAt = null; if (!rotateAngle.Equals(0)) { rotateAt = new RotateTransform(rotateAngle, textStart.X, textStart.Y); _drawContext.PushTransform(rotateAt); } Point textPoint = new Point(ctp.X, ctp.Y - yCorrection); Geometry textGeometry = textBuilder.Build(element, inputText, textPoint.X, textPoint.Y); if (textGeometry != null && !textGeometry.IsEmpty()) { // _drawContext.DrawGeometry(textBrush, textPen, ExtractTextPathGeometry(textGeometry)); _drawContext.DrawGeometry(textBrush, textPen, textGeometry); } //float bboxWidth = (float)formattedText.Width; double bboxWidth = textGeometry.Bounds.Width; if (alignment == TextAlignment.Center) { bboxWidth /= 2f; } else if (alignment == TextAlignment.Right) { bboxWidth = 0; } //ctp.X += bboxWidth + emSize / 4 + spacing; if (hasLetterSpacing) { ctp.X += bboxWidth + letterSpacing; } if (hasWordSpacing && char.IsWhiteSpace(text[i])) { if (hasLetterSpacing) { ctp.X += wordSpacing; } else { ctp.X += bboxWidth + wordSpacing; } } else { if (!hasLetterSpacing) { ctp.X += bboxWidth; } } if (rotateAt != null) { _drawContext.Pop(); } j++; } } else { if (this.IsMeasuring) { var textSize = textBuilder.MeasureText(element, text); this.AddTextWidth(ctp, textSize.Width); return; } var textContext = this.TextContext; if (textContext != null && textContext.IsPositionChanged(element) == false) { if (alignment == TextAlignment.Center && this.TextWidth > 0) { alignment = TextAlignment.Left; } } textBuilder.TextAlignment = alignment; textBuilder.Trimming = stringFormat.Trimming; if (textDecors != null && textDecors.Count != 0) { textBuilder.TextDecorations = textDecors; } //float xCorrection = 0; //if (alignment == TextAlignment.Left) // xCorrection = emSize * 1f / 6f; //else if (alignment == TextAlignment.Right) // xCorrection = -emSize * 1f / 6f; double yCorrection = textBuilder.Baseline; float rotateAngle = (float)rotate; Point textPoint = new Point(ctp.X, ctp.Y - yCorrection); RotateTransform rotateAt = null; if (!rotateAngle.Equals(0)) { rotateAt = new RotateTransform(rotateAngle, ctp.X, ctp.Y); _drawContext.PushTransform(rotateAt); } Geometry textGeometry = textBuilder.Build(element, text, textPoint.X, textPoint.Y); if (textGeometry != null && !textGeometry.IsEmpty()) { // _drawContext.DrawGeometry(textBrush, textPen, ExtractTextPathGeometry(textGeometry)); _drawContext.DrawGeometry(textBrush, textPen, textGeometry); } //float bboxWidth = (float)formattedText.Width; // double bboxWidth = textGeometry.Bounds.Width; double bboxWidth = textBuilder.Width; if (alignment == TextAlignment.Center) { bboxWidth /= 2f; } else if (alignment == TextAlignment.Right) { bboxWidth = 0; } //ctp.X += bboxWidth + emSize / 4; ctp.X += bboxWidth; if (rotateAt != null) { _drawContext.Pop(); } } }
public override void RenderTextRun(SvgTextContentElement element, ref Point ctp, string text, double rotate, WpfTextPlacement placement) { if (string.IsNullOrWhiteSpace(text)) { return; } double emSize = GetComputedFontSize(element); var fontFamilyInfo = GetTextFontFamilyInfo(element); WpfTextStringFormat stringFormat = GetTextStringFormat(element); if (fontFamilyInfo.FontFamilyType == WpfFontFamilyType.Svg) { WpfTextTuple textInfo = new WpfTextTuple(fontFamilyInfo, emSize, stringFormat, element); this.RenderTextRun(textInfo, ref ctp, text, rotate, placement); return; } FontFamily fontFamily = fontFamilyInfo.Family; FontStyle fontStyle = fontFamilyInfo.Style; FontWeight fontWeight = fontFamilyInfo.Weight; FontStretch fontStretch = fontFamilyInfo.Stretch; // Fix the use of Postscript fonts... WpfFontFamilyVisitor fontFamilyVisitor = _context.FontFamilyVisitor; if (!string.IsNullOrWhiteSpace(_actualFontName) && fontFamilyVisitor != null) { WpfFontFamilyInfo familyInfo = fontFamilyVisitor.Visit(_actualFontName, fontFamilyInfo, _context); if (familyInfo != null && !familyInfo.IsEmpty) { fontFamily = familyInfo.Family; fontWeight = familyInfo.Weight; fontStyle = familyInfo.Style; fontStretch = familyInfo.Stretch; } } WpfSvgPaint fillPaint = new WpfSvgPaint(_context, element, "fill"); Brush textBrush = fillPaint.GetBrush(); WpfSvgPaint strokePaint = new WpfSvgPaint(_context, element, "stroke"); Pen textPen = strokePaint.GetPen(); if (textBrush == null && textPen == null) { return; } bool isForcedPathMode = false; if (textBrush == null) { // If here, then the pen is not null, and so the fill cannot be null. // We set this to transparent for stroke only text path... textBrush = Brushes.Transparent; } else { // WPF gradient fill does not work well on text, use geometry to render it isForcedPathMode = (fillPaint.FillType == WpfFillType.Gradient); } if (textPen != null) { textPen.LineJoin = PenLineJoin.Round; // Better for text rendering isForcedPathMode = true; } TextDecorationCollection textDecors = GetTextDecoration(element); if (textDecors == null) { SvgTextBaseElement textElement = element.ParentNode as SvgTextBaseElement; if (textElement != null) { textDecors = GetTextDecoration(textElement); } } TextAlignment alignment = stringFormat.Alignment; bool hasWordSpacing = false; string wordSpaceText = element.GetAttribute("word-spacing"); double wordSpacing = 0; if (!string.IsNullOrWhiteSpace(wordSpaceText) && double.TryParse(wordSpaceText, out wordSpacing) && !wordSpacing.Equals(0)) { hasWordSpacing = true; } bool hasLetterSpacing = false; string letterSpaceText = element.GetAttribute("letter-spacing"); double letterSpacing = 0; if (!string.IsNullOrWhiteSpace(letterSpaceText) && double.TryParse(letterSpaceText, out letterSpacing) && !letterSpacing.Equals(0)) { hasLetterSpacing = true; } bool isRotatePosOnly = false; IList <WpfTextPosition> textPositions = null; int textPosCount = 0; if ((placement != null && placement.HasPositions)) { textPositions = placement.Positions; textPosCount = textPositions.Count; isRotatePosOnly = placement.IsRotateOnly; } var typeFace = new Typeface(fontFamily, fontStyle, fontWeight, fontStretch); if (textPositions != null && textPositions.Count != 0) { if (textPositions.Count == text.Trim().Length) //TODO: Best way to handle this... { text = text.Trim(); } } if (hasLetterSpacing || hasWordSpacing || textPositions != null) { double spacing = Convert.ToDouble(letterSpacing); int startSpaces = 0; for (int i = 0; i < text.Length; i++) { if (char.IsWhiteSpace(text[i])) { startSpaces++; } else { break; } } int j = 0; string inputText = string.Empty; for (int i = 0; i < text.Length; i++) { // Avoid rendering only spaces at the start of text run... if (i == 0 && startSpaces != 0) { inputText = text.Substring(0, startSpaces + 1); i += startSpaces; } else { inputText = new string(text[i], 1); } FormattedText formattedText = new FormattedText(inputText, _context.CultureInfo, stringFormat.Direction, typeFace, emSize, textBrush); if (this.IsMeasuring) { this.AddTextWidth(ctp, formattedText.WidthIncludingTrailingWhitespace); continue; } formattedText.Trimming = stringFormat.Trimming; formattedText.TextAlignment = stringFormat.Alignment; if (textDecors != null && textDecors.Count != 0) { formattedText.SetTextDecorations(textDecors); } WpfTextPosition?textPosition = null; if (textPositions != null && j < textPosCount) { textPosition = textPositions[j]; } //float xCorrection = 0; //if (alignment == TextAlignment.Left) // xCorrection = emSize * 1f / 6f; //else if (alignment == TextAlignment.Right) // xCorrection = -emSize * 1f / 6f; double yCorrection = formattedText.Baseline; float rotateAngle = (float)rotate; if (textPosition != null) { if (!isRotatePosOnly) { Point pt = textPosition.Value.Location; ctp.X = pt.X; ctp.Y = pt.Y; } rotateAngle = (float)textPosition.Value.Rotation; } Point textStart = ctp; RotateTransform rotateAt = null; if (!rotateAngle.Equals(0)) { rotateAt = new RotateTransform(rotateAngle, textStart.X, textStart.Y); _drawContext.PushTransform(rotateAt); } Point textPoint = new Point(ctp.X, ctp.Y - yCorrection); if (isForcedPathMode || _context.TextAsGeometry) { Geometry textGeometry = formattedText.BuildGeometry(textPoint); if (textGeometry != null && !textGeometry.IsEmpty()) { _drawContext.DrawGeometry(textBrush, textPen, ExtractTextPathGeometry(textGeometry)); this.IsTextPath = true; } else { _drawContext.DrawText(formattedText, textPoint); } } else { _drawContext.DrawText(formattedText, textPoint); } //float bboxWidth = (float)formattedText.Width; double bboxWidth = formattedText.WidthIncludingTrailingWhitespace; if (alignment == TextAlignment.Center) { bboxWidth /= 2f; } else if (alignment == TextAlignment.Right) { bboxWidth = 0; } //ctp.X += bboxWidth + emSize / 4 + spacing; if (hasLetterSpacing) { ctp.X += bboxWidth + letterSpacing; } if (hasWordSpacing && char.IsWhiteSpace(text[i])) { if (hasLetterSpacing) { ctp.X += wordSpacing; } else { ctp.X += bboxWidth + wordSpacing; } } else { if (!hasLetterSpacing) { ctp.X += bboxWidth; } } if (rotateAt != null) { _drawContext.Pop(); } j++; } } else { FormattedText formattedText = new FormattedText(text, _context.CultureInfo, stringFormat.Direction, typeFace, emSize, textBrush); if (this.IsMeasuring) { this.AddTextWidth(ctp, formattedText.WidthIncludingTrailingWhitespace); return; } var textContext = this.TextContext; if (textContext != null && textContext.IsPositionChanged(element) == false) { if (alignment == TextAlignment.Center && this.TextWidth > 0) { alignment = TextAlignment.Left; } } formattedText.TextAlignment = alignment; formattedText.Trimming = stringFormat.Trimming; if (textDecors != null && textDecors.Count != 0) { formattedText.SetTextDecorations(textDecors); } //float xCorrection = 0; //if (alignment == TextAlignment.Left) // xCorrection = emSize * 1f / 6f; //else if (alignment == TextAlignment.Right) // xCorrection = -emSize * 1f / 6f; double yCorrection = formattedText.Baseline; float rotateAngle = (float)rotate; Point textPoint = new Point(ctp.X, ctp.Y - yCorrection); RotateTransform rotateAt = null; if (!rotateAngle.Equals(0)) { rotateAt = new RotateTransform(rotateAngle, ctp.X, ctp.Y); _drawContext.PushTransform(rotateAt); } if (isForcedPathMode || _context.TextAsGeometry) { Geometry textGeometry = formattedText.BuildGeometry(textPoint); if (textGeometry != null && !textGeometry.IsEmpty()) { _drawContext.DrawGeometry(textBrush, textPen, ExtractTextPathGeometry(textGeometry)); this.IsTextPath = true; } else { _drawContext.DrawText(formattedText, textPoint); } } else { _drawContext.DrawText(formattedText, textPoint); } //float bboxWidth = (float)formattedText.Width; double bboxWidth = formattedText.WidthIncludingTrailingWhitespace; if (alignment == TextAlignment.Center) { bboxWidth /= 2f; } else if (alignment == TextAlignment.Right) { bboxWidth = 0; } //ctp.X += bboxWidth + emSize / 4; ctp.X += bboxWidth; if (rotateAt != null) { _drawContext.Pop(); } } }
public WpfPathTextBuilder(SvgTextBaseElement textElement) { _textElement = textElement; _pathChars = new List <WpfPathChar>(); }
public void SetPosition(Point pos, SvgTextPathElement pathElement, SvgTextBaseElement textElement) { _contentPos = pos; _startOffset = this.GetStartOffset(pathElement, textElement); }