private float GetComputedFontSize(SvgTextContentElement element) { string str = element.GetPropertyValue("font-size"); float fontSize = 12; if (str.EndsWith("%")) { // percentage of inherited value } else if (new Regex(@"^\d").IsMatch(str)) { // svg length fontSize = (float)new SvgLength(element, "font-size", SvgLengthDirection.Viewport, str, "10px").Value; } else if (str == "larger") { } else if (str == "smaller") { } else { // check for absolute value } return fontSize; }
private void RenderTextRunV(SvgTextContentElement element, ref Point ctp, string text, double rotate, WpfTextPlacement placement) { if (String.IsNullOrEmpty(text) || _vertRenderer == null) return; if (placement != null) { placement.UpdatePositions(text); } _vertRenderer.RenderTextRun(element, ref ctp, text, rotate, placement); }
private void AddGraphicsPath(SvgTextContentElement element, ref PointF ctp, string text) { if (text.Length == 0) return; float emSize = GetComputedFontSize(element); FontFamily family = GetGDIFontFamily(element, emSize); int style = GetGDIFontStyle(element); StringFormat sf = GetGDIStringFormat(element); GraphicsPath textGeometry = new GraphicsPath(); float xCorrection = 0; if (sf.Alignment == StringAlignment.Near) xCorrection = emSize * 1 / 6; else if (sf.Alignment == StringAlignment.Far) xCorrection = -emSize * 1 / 6; float yCorrection = (float)(family.GetCellAscent(FontStyle.Regular)) / (float)(family.GetEmHeight(FontStyle.Regular)) * emSize; // TODO: font property PointF p = new PointF(ctp.X - xCorrection, ctp.Y - yCorrection); textGeometry.AddString(text, family, style, emSize, p, sf); if (!textGeometry.GetBounds().IsEmpty) { float bboxWidth = textGeometry.GetBounds().Width; if (sf.Alignment == StringAlignment.Center) bboxWidth /= 2; else if (sf.Alignment == StringAlignment.Far) bboxWidth = 0; ctp.X += bboxWidth + emSize / 4; } GdiSvgPaint fillPaint = new GdiSvgPaint(element, "fill"); Brush brush = fillPaint.GetBrush(textGeometry); GdiSvgPaint strokePaint = new GdiSvgPaint(element, "stroke"); Pen pen = strokePaint.GetPen(textGeometry); if (brush != null) { if (brush is PathGradientBrush) { GdiGradientFill gps = fillPaint.PaintFill as GdiGradientFill; _graphics.SetClip(gps.GetRadialGradientRegion(textGeometry.GetBounds()), CombineMode.Exclude); SolidBrush tempBrush = new SolidBrush(((PathGradientBrush)brush).InterpolationColors.Colors[0]); _graphics.FillPath(this, tempBrush, textGeometry); tempBrush.Dispose(); _graphics.ResetClip(); } _graphics.FillPath(this, brush, textGeometry); brush.Dispose(); } if (pen != null) { if (pen.Brush is PathGradientBrush) { GdiGradientFill gps = strokePaint.PaintFill as GdiGradientFill; GdiGraphicsContainer container = _graphics.BeginContainer(); _graphics.SetClip(gps.GetRadialGradientRegion(textGeometry.GetBounds()), CombineMode.Exclude); SolidBrush tempBrush = new SolidBrush(((PathGradientBrush)pen.Brush).InterpolationColors.Colors[0]); Pen tempPen = new Pen(tempBrush, pen.Width); _graphics.DrawPath(this, tempPen, textGeometry); tempPen.Dispose(); tempBrush.Dispose(); _graphics.EndContainer(container); } _graphics.DrawPath(this, pen, textGeometry); pen.Dispose(); } textGeometry.Dispose(); }
public override void RenderSingleLineText(SvgTextContentElement element, ref Point ctp, string text, double rotate, WpfTextPlacement placement) { if (String.IsNullOrEmpty(text)) return; int vertOrientation = -1; int horzOrientation = -1; string orientationText = element.GetPropertyValue("glyph-orientation-vertical"); if (!String.IsNullOrEmpty(orientationText)) { double orientationValue = 0; if (Double.TryParse(orientationText, out orientationValue)) { vertOrientation = (int)orientationValue; } } orientationText = element.GetPropertyValue("glyph-orientation-horizontal"); if (!String.IsNullOrEmpty(orientationText)) { double orientationValue = 0; if (Double.TryParse(orientationText, out orientationValue)) { horzOrientation = (int)orientationValue; } } Point startPoint = ctp; IList<WpfTextRun> textRunList = WpfTextRun.BreakWords(text, vertOrientation, horzOrientation); for (int tr = 0; tr < textRunList.Count; tr++) { // For unknown reasons, FormattedText will split a text like "-70%" into two parts "-" // and "70%". We provide a shift to account for the split... double baselineShiftX = 0; double baselineShiftY = 0; WpfTextRun textRun = textRunList[tr]; DrawingGroup verticalGroup = new DrawingGroup(); DrawingContext verticalContext = verticalGroup.Open(); DrawingContext currentContext = _textContext; _textContext = verticalContext; this.DrawSingleLineText(element, ref ctp, textRun, rotate, placement); verticalContext.Close(); _textContext = currentContext; if (verticalGroup.Children.Count == 1) { DrawingGroup textGroup = verticalGroup.Children[0] as DrawingGroup; if (textGroup != null) { verticalGroup = textGroup; } } string runText = textRun.Text; int charCount = runText.Length; double totalHeight = 0; DrawingCollection drawings = verticalGroup.Children; int itemCount = drawings != null ? drawings.Count : 0; for (int i = 0; i < itemCount; i++) { Drawing textDrawing = drawings[i]; DrawingGroup textGroup = textDrawing as DrawingGroup; if (vertOrientation == -1) { if (textGroup != null) { for (int j = 0; j < textGroup.Children.Count; j++) { GlyphRunDrawing glyphDrawing = textGroup.Children[j] as GlyphRunDrawing; if (glyphDrawing != null) { if (textRun.IsLatin) { GlyphRun glyphRun = glyphDrawing.GlyphRun; IList<UInt16> glyphIndices = glyphRun.GlyphIndices; IDictionary<ushort, double> allGlyphWeights = glyphRun.GlyphTypeface.AdvanceWidths; double lastAdvanceWeight = allGlyphWeights[glyphIndices[glyphIndices.Count - 1]] * glyphRun.FontRenderingEmSize; totalHeight += glyphRun.ComputeAlignmentBox().Width + lastAdvanceWeight / 2d; } else { totalHeight += ChangeGlyphOrientation(glyphDrawing, baselineShiftX, baselineShiftY, false); } } } } else { GlyphRunDrawing glyphDrawing = textDrawing as GlyphRunDrawing; if (glyphDrawing != null) { if (textRun.IsLatin) { GlyphRun glyphRun = glyphDrawing.GlyphRun; IList<UInt16> glyphIndices = glyphRun.GlyphIndices; IDictionary<ushort, double> allGlyphWeights = glyphRun.GlyphTypeface.AdvanceWidths; double lastAdvanceWeight = allGlyphWeights[glyphIndices[glyphIndices.Count - 1]] * glyphRun.FontRenderingEmSize; totalHeight += glyphRun.ComputeAlignmentBox().Width + lastAdvanceWeight / 2d; } else { totalHeight += ChangeGlyphOrientation(glyphDrawing, baselineShiftX, baselineShiftY, false); } } } } else if (vertOrientation == 0) { if (textGroup != null) { for (int j = 0; j < textGroup.Children.Count; j++) { GlyphRunDrawing glyphDrawing = textGroup.Children[j] as GlyphRunDrawing; if (glyphDrawing != null) { baselineShiftX = ChangeGlyphOrientation(glyphDrawing, baselineShiftX, baselineShiftY, textRun.IsLatin); totalHeight += baselineShiftX; } } } else { GlyphRunDrawing glyphDrawing = textDrawing as GlyphRunDrawing; if (textDrawing != null) { totalHeight += ChangeGlyphOrientation(glyphDrawing, baselineShiftX, baselineShiftY, textRun.IsLatin); } } } else { throw new NotImplementedException(); } } if (!this.IsMeasuring) { _textContext.DrawDrawing(verticalGroup); } if (tr < textRunList.Count) { ctp.X = startPoint.X; ctp.Y = startPoint.Y + totalHeight; startPoint.Y += totalHeight; } } }
public override void RenderTextRun(SvgTextContentElement element, ref Point ctp, string text, double rotate, WpfTextPlacement placement) { }
private StringFormat GetGDIStringFormat(SvgTextContentElement element) { StringFormat sf = new StringFormat(); bool doAlign = true; if (element is SvgTSpanElement || element is SvgTRefElement) { SvgTextPositioningElement posElement = (SvgTextPositioningElement)element; if (posElement.X.AnimVal.NumberOfItems == 0) doAlign = false; } if (doAlign) { string anchor = element.GetPropertyValue("text-anchor"); if (anchor == "middle") sf.Alignment = StringAlignment.Center; if (anchor == "end") sf.Alignment = StringAlignment.Far; } string dir = element.GetPropertyValue("direction"); if (dir == "rtl") { if (sf.Alignment == StringAlignment.Far) sf.Alignment = StringAlignment.Near; else if (sf.Alignment == StringAlignment.Near) sf.Alignment = StringAlignment.Far; 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 string TrimText(SvgTextContentElement element, string val) { Regex tabNewline = new Regex(@"[\n\f\t]"); if (element.XmlSpace != "preserve") val = val.Replace("\n", String.Empty); val = tabNewline.Replace(val, " "); if (element.XmlSpace == "preserve") return val; else return val.Trim(); }
protected FontFamily GetTextFontFamily(SvgTextContentElement element, double fontSize) { _actualFontName = null; string fontFamily = element.GetPropertyValue("font-family"); string[] fontNames = fontNames = fontFamily.Split(new char[1] { ',' }); FontFamily family; foreach (string fn in fontNames) { try { string fontName = fn.Trim(new char[] { ' ', '\'', '"' }); if (String.Equals(fontName, "serif", StringComparison.OrdinalIgnoreCase)) { family = WpfDrawingSettings.GenericSerif; } else if (String.Equals(fontName, "sans-serif", StringComparison.OrdinalIgnoreCase)) { family = WpfDrawingSettings.GenericSansSerif; } else if (String.Equals(fontName, "monospace", StringComparison.OrdinalIgnoreCase)) { family = WpfDrawingSettings.GenericMonospace; } else { family = new FontFamily(fontName); _actualFontName = fontName; } return family; } catch { } } // no known font-family was found => default to Arial return WpfDrawingSettings.DefaultFontFamily; }
protected FontStretch GetTextFontStretch(SvgTextContentElement element) { string fontStretch = element.GetPropertyValue("font-stretch"); if (String.IsNullOrEmpty(fontStretch)) { return FontStretches.Normal; } switch (fontStretch) { case "normal": return FontStretches.Normal; case "ultra-condensed": return FontStretches.UltraCondensed; case "extra-condensed": return FontStretches.ExtraCondensed; case "condensed": return FontStretches.Condensed; case "semi-condensed": return FontStretches.SemiCondensed; case "semi-expanded": return FontStretches.SemiExpanded; case "expanded": return FontStretches.Expanded; case "extra-expanded": return FontStretches.ExtraExpanded; case "ultra-expanded": return FontStretches.UltraExpanded; } return FontStretches.Normal; }
public abstract void RenderTextRun(SvgTextContentElement element, ref Point startPos, string text, double rotate, WpfTextPlacement placement);
protected TextDecorationCollection GetTextDecoration(SvgTextContentElement element) { string textDeco = element.GetPropertyValue("text-decoration"); if (textDeco == "line-through") { return TextDecorations.Strikethrough; } if (textDeco == "underline") { return TextDecorations.Underline; } if (textDeco == "overline") { return TextDecorations.OverLine; } return null; }
public static string TrimText(SvgTextContentElement element, string val) { if (element.XmlSpace != "preserve") val = val.Replace("\n", String.Empty); val = _tabNewline.Replace(val, " "); if (element.XmlSpace == "preserve" || element.XmlSpace == "default") { return val; } else { return val.Trim(); } }
public static double GetComputedFontSize(SvgTextContentElement element) { string str = element.GetPropertyValue("font-size"); double fontSize = 12; if (str.EndsWith("%")) { // percentage of inherited value } else if (_decimalNumber.IsMatch(str)) { // svg length fontSize = new SvgLength(element, "font-size", SvgLengthDirection.Viewport, str, "10px").Value; } else if (str == "larger") { } else if (str == "smaller") { } else { // check for absolute value } return fontSize; }
private void RenderTextPath(SvgTextContentElement element, WpfTextOnPathDrawing pathDrawing, string text, Point origin, double rotate, WpfTextPlacement placement) { if (String.IsNullOrEmpty(text)) { return; } double emSize = GetComputedFontSize(element); FontFamily fontFamily = GetTextFontFamily(element, emSize); FontStyle fontStyle = GetTextFontStyle(element); FontWeight fontWeight = GetTextFontWeight(element); FontStretch fontStretch = GetTextFontStretch(element); WpfTextStringFormat stringFormat = GetTextStringFormat(element); // Fix the use of Postscript fonts... WpfFontFamilyVisitor fontFamilyVisitor = _drawContext.FontFamilyVisitor; if (!String.IsNullOrEmpty(_actualFontName) && fontFamilyVisitor != null) { WpfFontFamilyInfo currentFamily = new WpfFontFamilyInfo(fontFamily, fontWeight, fontStyle, fontStretch); WpfFontFamilyInfo familyInfo = fontFamilyVisitor.Visit(_actualFontName, currentFamily, _drawContext); if (familyInfo != null && !familyInfo.IsEmpty) { fontFamily = familyInfo.Family; fontWeight = familyInfo.Weight; fontStyle = familyInfo.Style; fontStretch = familyInfo.Stretch; } } WpfSvgPaint fillPaint = new WpfSvgPaint(_drawContext, element, "fill"); Brush textBrush = fillPaint.GetBrush(); WpfSvgPaint strokePaint = new WpfSvgPaint(_drawContext, element, "stroke"); Pen pen = strokePaint.GetPen(); TextDecorationCollection textDecors = GetTextDecoration(element); TextAlignment alignment = stringFormat.Alignment; pathDrawing.FontSize = emSize; pathDrawing.FontFamily = fontFamily; pathDrawing.FontWeight = fontWeight; pathDrawing.FontStretch = fontStretch; pathDrawing.Foreground = textBrush; pathDrawing.AddTextPath(text, origin); }
private FontFamily GetGDIFontFamily(SvgTextContentElement element, float fontSize) { string fontFamily = element.GetPropertyValue("font-family"); string[] fontNames = fontNames = fontFamily.Split(new char[1] { ',' }); FontFamily family; foreach (string fn in fontNames) { try { string fontName = fn.Trim(new char[] { ' ', '\'', '"' }); if (fontName == "serif") family = FontFamily.GenericSerif; else if (fontName == "sans-serif") family = FontFamily.GenericSansSerif; else if (fontName == "monospace") family = FontFamily.GenericMonospace; else family = new FontFamily(fontName); // Font(,fontSize).FontFamily; return family; } catch { } } // no known font-family was found => default to arial return new FontFamily("Arial"); }
protected FontStyle GetTextFontStyle(SvgTextContentElement element) { string fontStyle = element.GetPropertyValue("font-style"); if (String.IsNullOrEmpty(fontStyle)) { return FontStyles.Normal; } if (fontStyle == "normal") { return FontStyles.Normal; } if (fontStyle == "italic") { return FontStyles.Italic; } if (fontStyle == "oblique") { return FontStyles.Oblique; } return FontStyles.Normal; }
private int GetGDIFontStyle(SvgTextContentElement element) { int style = (int)FontStyle.Regular; string fontWeight = element.GetPropertyValue("font-weight"); if (fontWeight == "bold" || fontWeight == "bolder" || fontWeight == "600" || fontWeight == "700" || fontWeight == "800" || fontWeight == "900") { style = style | (int)FontStyle.Bold; } if (element.GetPropertyValue("font-style") == "italic") { style = style | (int)FontStyle.Italic; } string textDeco = element.GetPropertyValue("text-decoration"); if (textDeco == "line-through") { style = style | (int)FontStyle.Strikeout; } else if (textDeco == "underline") { style = style | (int)FontStyle.Underline; } return style; }
protected FontWeight GetTextFontWeight(SvgTextContentElement element) { string fontWeight = element.GetPropertyValue("font-weight"); if (String.IsNullOrEmpty(fontWeight)) { return FontWeights.Normal; } switch (fontWeight) { case "normal": return FontWeights.Normal; case "bold": return FontWeights.Bold; case "100": return FontWeights.Thin; case "200": return FontWeights.ExtraLight; case "300": return FontWeights.Light; case "400": return FontWeights.Normal; case "500": return FontWeights.Medium; case "600": return FontWeights.SemiBold; case "700": return FontWeights.Bold; case "800": return FontWeights.ExtraBold; case "900": return FontWeights.Black; case "950": return FontWeights.UltraBlack; } if (String.Equals(fontWeight, "bolder", StringComparison.OrdinalIgnoreCase)) { SvgTransformableElement parentElement = element.ParentNode as SvgTransformableElement; if (parentElement != null) { fontWeight = parentElement.GetPropertyValue("font-weight"); if (!String.IsNullOrEmpty(fontWeight)) { return this.GetBolderFontWeight(fontWeight); } } return FontWeights.ExtraBold; } if (String.Equals(fontWeight, "lighter", StringComparison.OrdinalIgnoreCase)) { SvgTransformableElement parentElement = element.ParentNode as SvgTransformableElement; if (parentElement != null) { fontWeight = parentElement.GetPropertyValue("font-weight"); if (!String.IsNullOrEmpty(fontWeight)) { return this.GetLighterFontWeight(fontWeight); } } return FontWeights.Light; } return FontWeights.Normal; }
private string GetText(SvgTextContentElement element, XmlNode child) { return TrimText(element, child.Value); }
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; } string dir = element.GetPropertyValue("direction"); bool isRightToLeft = (dir == "rtl"); sf.Direction = isRightToLeft ? FlowDirection.RightToLeft : FlowDirection.LeftToRight; if (doAlign) { string anchor = element.GetPropertyValue("text-anchor"); if (isRightToLeft) { if (anchor == "middle") sf.Anchor = WpfTextAnchor.Middle; else if (anchor == "end") sf.Anchor = WpfTextAnchor.Start; else sf.Anchor = WpfTextAnchor.End; } else { if (anchor == "middle") sf.Anchor = WpfTextAnchor.Middle; else if (anchor == "end") sf.Anchor = WpfTextAnchor.End; } } else { SvgTextElement textElement = element.ParentNode as SvgTextElement; if (textElement != null) { string anchor = textElement.GetPropertyValue("text-anchor"); if (isRightToLeft) { if (anchor == "middle") sf.Anchor = WpfTextAnchor.Middle; else if (anchor == "end") sf.Anchor = WpfTextAnchor.Start; else sf.Anchor = WpfTextAnchor.End; } else { if (anchor == "middle") sf.Anchor = WpfTextAnchor.Middle; else if (anchor == "end") 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; }
public override void RenderTextRun(SvgTextContentElement element, ref Point ctp, string text, double rotate, WpfTextPlacement placement) { if (String.IsNullOrEmpty(text)) return; double emSize = GetComputedFontSize(element); FontFamily fontFamily = GetTextFontFamily(element, emSize); FontStyle fontStyle = GetTextFontStyle(element); FontWeight fontWeight = GetTextFontWeight(element); FontStretch fontStretch = GetTextFontStretch(element); WpfTextStringFormat stringFormat = GetTextStringFormat(element); // Fix the use of Postscript fonts... WpfFontFamilyVisitor fontFamilyVisitor = _drawContext.FontFamilyVisitor; if (!String.IsNullOrEmpty(_actualFontName) && fontFamilyVisitor != null) { WpfFontFamilyInfo currentFamily = new WpfFontFamilyInfo(fontFamily, fontWeight, fontStyle, fontStretch); WpfFontFamilyInfo familyInfo = fontFamilyVisitor.Visit(_actualFontName, currentFamily,_drawContext); if (familyInfo != null && !familyInfo.IsEmpty) { fontFamily = familyInfo.Family; fontWeight = familyInfo.Weight; fontStyle = familyInfo.Style; fontStretch = familyInfo.Stretch; } } WpfSvgPaint fillPaint = new WpfSvgPaint(_drawContext, element, "fill"); Brush textBrush = fillPaint.GetBrush(); WpfSvgPaint strokePaint = new WpfSvgPaint(_drawContext, element, "stroke"); Pen textPen = strokePaint.GetPen(); if (textBrush == null && textPen == null) { return; } else 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; } TextDecorationCollection textDecors = GetTextDecoration(element); if (textDecors == null) { SvgTextElement textElement = element.ParentNode as SvgTextElement; if (textElement != null) { textDecors = GetTextDecoration(textElement); } } TextAlignment alignment = stringFormat.Alignment; bool hasWordSpacing = false; string wordSpaceText = element.GetAttribute("word-spacing"); double wordSpacing = 0; if (!String.IsNullOrEmpty(wordSpaceText) && Double.TryParse(wordSpaceText, out wordSpacing) && (float)wordSpacing != 0) { hasWordSpacing = true; } bool hasLetterSpacing = false; string letterSpaceText = element.GetAttribute("letter-spacing"); double letterSpacing = 0; if (!String.IsNullOrEmpty(letterSpaceText) && Double.TryParse(letterSpaceText, out letterSpacing) && (float)letterSpacing != 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; } if (hasLetterSpacing || hasWordSpacing || textPositions != null) { double spacing = Convert.ToDouble(letterSpacing); for (int i = 0; i < text.Length; i++) { FormattedText formattedText = new FormattedText(new string(text[i], 1), _drawContext.CultureInfo, stringFormat.Direction, new Typeface(fontFamily, fontStyle, fontWeight, fontStretch), emSize, textBrush); if (this.IsMeasuring) { this.AddTextWidth(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 && i < textPosCount) { textPosition = textPositions[i]; } //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 != 0) { rotateAt = new RotateTransform(rotateAngle, textStart.X, textStart.Y); _textContext.PushTransform(rotateAt); } Point textPoint = new Point(ctp.X, ctp.Y - yCorrection); if (textPen != null || _drawContext.TextAsGeometry) { Geometry textGeometry = formattedText.BuildGeometry(textPoint); if (textGeometry != null && !textGeometry.IsEmpty()) { _textContext.DrawGeometry(textBrush, textPen, ExtractTextPathGeometry(textGeometry)); this.IsTextPath = true; } else { _textContext.DrawText(formattedText, textPoint); } } else { _textContext.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) { _textContext.Pop(); } } } else { FormattedText formattedText = new FormattedText(text, _drawContext.CultureInfo, stringFormat.Direction, new Typeface(fontFamily, fontStyle, fontWeight, fontStretch), emSize, textBrush); if (this.IsMeasuring) { this.AddTextWidth(formattedText.WidthIncludingTrailingWhitespace); return; } 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 != 0) { rotateAt = new RotateTransform(rotateAngle, ctp.X, ctp.Y); _textContext.PushTransform(rotateAt); } if (textPen != null || _drawContext.TextAsGeometry) { Geometry textGeometry = formattedText.BuildGeometry(textPoint); if (textGeometry != null && !textGeometry.IsEmpty()) { _textContext.DrawGeometry(textBrush, textPen, ExtractTextPathGeometry(textGeometry)); this.IsTextPath = true; } else { _textContext.DrawText(formattedText, textPoint); } } else { _textContext.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) { _textContext.Pop(); } } }
private void RenderSingleLineTextV(SvgTextContentElement element, ref Point ctp, string text, double rotate, WpfTextPlacement placement) { if (String.IsNullOrEmpty(text) || _vertRenderer == null) return; string targetText = text.Trim(); if (placement != null) { placement.UpdatePositions(targetText); } _vertRenderer.RenderSingleLineText(element, ref ctp, targetText, rotate, placement); }
private void DrawTextRun(SvgTextContentElement element, ref Point ctp, WpfTextRun textRun, double rotate, WpfTextPlacement placement) { if (textRun == null || textRun.IsEmpty) return; string text = textRun.Text; double emSize = GetComputedFontSize(element); FontFamily fontFamily = GetTextFontFamily(element, emSize); FontStyle fontStyle = GetTextFontStyle(element); FontWeight fontWeight = GetTextFontWeight(element); FontStretch fontStretch = GetTextFontStretch(element); WpfTextStringFormat stringFormat = GetTextStringFormat(element); // Fix the use of Postscript fonts... WpfFontFamilyVisitor fontFamilyVisitor = _drawContext.FontFamilyVisitor; if (!String.IsNullOrEmpty(_actualFontName) && fontFamilyVisitor != null) { WpfFontFamilyInfo currentFamily = new WpfFontFamilyInfo(fontFamily, fontWeight, fontStyle, fontStretch); WpfFontFamilyInfo familyInfo = fontFamilyVisitor.Visit(_actualFontName, currentFamily, _drawContext); if (familyInfo != null && !familyInfo.IsEmpty) { fontFamily = familyInfo.Family; fontWeight = familyInfo.Weight; fontStyle = familyInfo.Style; fontStretch = familyInfo.Stretch; } } WpfSvgPaint fillPaint = new WpfSvgPaint(_drawContext, element, "fill"); Brush textBrush = fillPaint.GetBrush(); WpfSvgPaint strokePaint = new WpfSvgPaint(_drawContext, element, "stroke"); Pen textPen = strokePaint.GetPen(); if (textBrush == null && textPen == null) { return; } else 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; } TextDecorationCollection textDecors = GetTextDecoration(element); TextAlignment alignment = stringFormat.Alignment; string letterSpacing = element.GetAttribute("letter-spacing"); if (String.IsNullOrEmpty(letterSpacing)) { FormattedText formattedText = new FormattedText(text, textRun.IsLatin ? _drawContext.EnglishCultureInfo : _drawContext.CultureInfo, stringFormat.Direction, new Typeface(fontFamily, fontStyle, fontWeight, fontStretch), emSize, textBrush); formattedText.TextAlignment = stringFormat.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; Point textPoint = new Point(ctp.X, ctp.Y - yCorrection); RotateTransform rotateAt = new RotateTransform(90, ctp.X, ctp.Y); _textContext.PushTransform(rotateAt); _textContext.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) { _textContext.Pop(); } } else { RotateTransform rotateAt = new RotateTransform(90, ctp.X, ctp.Y); _textContext.PushTransform(rotateAt); float spacing = Convert.ToSingle(letterSpacing); for (int i = 0; i < text.Length; i++) { FormattedText formattedText = new FormattedText(new string(text[i], 1), textRun.IsLatin ? _drawContext.EnglishCultureInfo : _drawContext.CultureInfo, stringFormat.Direction, new Typeface(fontFamily, fontStyle, fontWeight, fontStretch), emSize, textBrush); formattedText.Trimming = stringFormat.Trimming; formattedText.TextAlignment = stringFormat.Alignment; 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; Point textPoint = new Point(ctp.X, ctp.Y - yCorrection); _textContext.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; ctp.X += bboxWidth + spacing; } if (rotateAt != null) { _textContext.Pop(); } } }
public override void RenderSingleLineText(SvgTextContentElement element, ref Point ctp, string text, double rotate, WpfTextPlacement placement) { this.RenderTextPath((SvgTextPathElement)element, ref ctp, rotate, placement); }