[12762] | 1 | using System;
|
---|
| 2 | using System.Xml;
|
---|
| 3 | using System.Linq;
|
---|
| 4 | using System.Text;
|
---|
| 5 | using System.Collections.Generic;
|
---|
| 6 |
|
---|
| 7 | using System.Windows;
|
---|
| 8 | using System.Windows.Media;
|
---|
| 9 |
|
---|
| 10 | using SharpVectors.Dom.Css;
|
---|
| 11 | using SharpVectors.Dom.Svg;
|
---|
| 12 |
|
---|
| 13 | using SharpVectors.Renderers.Wpf;
|
---|
| 14 |
|
---|
| 15 | namespace SharpVectors.Renderers.Texts
|
---|
| 16 | {
|
---|
| 17 | public sealed class WpfPathTextRenderer : WpfTextRenderer
|
---|
| 18 | {
|
---|
| 19 | #region Private Fields
|
---|
| 20 |
|
---|
| 21 | #endregion
|
---|
| 22 |
|
---|
| 23 | #region Constructors and Destructor
|
---|
| 24 |
|
---|
| 25 | public WpfPathTextRenderer(SvgTextElement textElement, WpfTextRendering textRendering)
|
---|
| 26 | : base(textElement, textRendering)
|
---|
| 27 | {
|
---|
| 28 | }
|
---|
| 29 |
|
---|
| 30 | #endregion
|
---|
| 31 |
|
---|
| 32 | #region Public Methods
|
---|
| 33 |
|
---|
| 34 | public override void RenderSingleLineText(SvgTextContentElement element,
|
---|
| 35 | ref Point ctp, string text, double rotate, WpfTextPlacement placement)
|
---|
| 36 | {
|
---|
| 37 | this.RenderTextPath((SvgTextPathElement)element, ref ctp, rotate, placement);
|
---|
| 38 | }
|
---|
| 39 |
|
---|
| 40 | public override void RenderTextRun(SvgTextContentElement element,
|
---|
| 41 | ref Point ctp, string text, double rotate, WpfTextPlacement placement)
|
---|
| 42 | {
|
---|
| 43 | }
|
---|
| 44 |
|
---|
| 45 | #endregion
|
---|
| 46 |
|
---|
| 47 | #region Private Methods
|
---|
| 48 |
|
---|
| 49 | private void RenderTextPath(SvgTextPathElement textPath, ref Point ctp,
|
---|
| 50 | double rotate, WpfTextPlacement placement)
|
---|
| 51 | {
|
---|
| 52 | if (textPath.ChildNodes == null || textPath.ChildNodes.Count == 0)
|
---|
| 53 | {
|
---|
| 54 | return;
|
---|
| 55 | }
|
---|
| 56 |
|
---|
| 57 | SvgElement targetPath = textPath.ReferencedElement as SvgElement;
|
---|
| 58 | if (targetPath == null)
|
---|
| 59 | {
|
---|
| 60 | return;
|
---|
| 61 | }
|
---|
| 62 |
|
---|
| 63 | PathGeometry pathGeometry = WpfRendering.CreateGeometry(targetPath, true) as PathGeometry;
|
---|
| 64 | if (pathGeometry == null)
|
---|
| 65 | {
|
---|
| 66 | return;
|
---|
| 67 | }
|
---|
| 68 |
|
---|
| 69 | this.IsTextPath = true;
|
---|
| 70 |
|
---|
| 71 | WpfTextOnPathDrawing pathDrawing = new WpfTextOnPathDrawing();
|
---|
| 72 |
|
---|
| 73 | pathDrawing.BeginTextPath();
|
---|
| 74 |
|
---|
| 75 | XmlNodeType nodeType = XmlNodeType.None;
|
---|
| 76 |
|
---|
| 77 | foreach (XmlNode child in textPath.ChildNodes)
|
---|
| 78 | {
|
---|
| 79 | nodeType = child.NodeType;
|
---|
| 80 | if (nodeType == XmlNodeType.Text)
|
---|
| 81 | {
|
---|
| 82 | RenderTextPath(textPath, pathDrawing, GetText(textPath, child),
|
---|
| 83 | new Point(ctp.X, ctp.Y), rotate, placement);
|
---|
| 84 | }
|
---|
| 85 | else if (nodeType == XmlNodeType.Element)
|
---|
| 86 | {
|
---|
| 87 | string nodeName = child.Name;
|
---|
| 88 | if (String.Equals(nodeName, "tref"))
|
---|
| 89 | {
|
---|
| 90 | RenderTRefPath((SvgTRefElement)child, pathDrawing, ref ctp);
|
---|
| 91 | }
|
---|
| 92 | else if (String.Equals(nodeName, "tspan"))
|
---|
| 93 | {
|
---|
| 94 | RenderTSpanPath((SvgTSpanElement)child, pathDrawing, ref ctp);
|
---|
| 95 | }
|
---|
| 96 | }
|
---|
| 97 | }
|
---|
| 98 |
|
---|
| 99 | WpfTextStringFormat stringFormat = GetTextStringFormat(_textElement);
|
---|
| 100 |
|
---|
| 101 | ISvgAnimatedLength pathOffset = textPath.StartOffset;
|
---|
| 102 | SvgTextPathMethod pathMethod = (SvgTextPathMethod)textPath.Method.BaseVal;
|
---|
| 103 | SvgTextPathSpacing pathSpacing = (SvgTextPathSpacing)textPath.Spacing.BaseVal;
|
---|
| 104 | pathDrawing.DrawTextPath(_textContext, pathGeometry, pathOffset,
|
---|
| 105 | stringFormat.Alignment, pathMethod, pathSpacing);
|
---|
| 106 |
|
---|
| 107 | pathDrawing.EndTextPath();
|
---|
| 108 | }
|
---|
| 109 |
|
---|
| 110 | private void RenderTRefPath(SvgTRefElement element, WpfTextOnPathDrawing pathDrawing,
|
---|
| 111 | ref Point ctp)
|
---|
| 112 | {
|
---|
| 113 | WpfTextPlacement placement = GetCurrentTextPosition(element, ctp);
|
---|
| 114 | ctp = placement.Location;
|
---|
| 115 | double rotate = placement.Rotation;
|
---|
| 116 | if (!placement.HasPositions)
|
---|
| 117 | {
|
---|
| 118 | placement = null; // Render it useless.
|
---|
| 119 | }
|
---|
| 120 |
|
---|
| 121 | this.RenderTextPath(element, pathDrawing, GetTRefText(element),
|
---|
| 122 | new Point(ctp.X, ctp.Y), rotate, placement);
|
---|
| 123 | }
|
---|
| 124 |
|
---|
| 125 | private void RenderTSpanPath(SvgTSpanElement element, WpfTextOnPathDrawing pathDrawing,
|
---|
| 126 | ref Point ctp)
|
---|
| 127 | {
|
---|
| 128 | WpfTextPlacement placement = GetCurrentTextPosition(element, ctp);
|
---|
| 129 | ctp = placement.Location;
|
---|
| 130 | double rotate = placement.Rotation;
|
---|
| 131 | if (!placement.HasPositions)
|
---|
| 132 | {
|
---|
| 133 | placement = null; // Render it useless.
|
---|
| 134 | }
|
---|
| 135 |
|
---|
| 136 | string sBaselineShift = element.GetPropertyValue("baseline-shift").Trim();
|
---|
| 137 | double shiftBy = 0;
|
---|
| 138 |
|
---|
| 139 | if (sBaselineShift.Length > 0)
|
---|
| 140 | {
|
---|
| 141 | SvgTextElement textElement = (SvgTextElement)element.SelectSingleNode("ancestor::svg:text",
|
---|
| 142 | element.OwnerDocument.NamespaceManager);
|
---|
| 143 |
|
---|
| 144 | double textFontSize = GetComputedFontSize(textElement);
|
---|
| 145 | if (sBaselineShift.EndsWith("%"))
|
---|
| 146 | {
|
---|
| 147 | shiftBy = SvgNumber.ParseNumber(sBaselineShift.Substring(0,
|
---|
| 148 | sBaselineShift.Length - 1)) / 100f * textFontSize;
|
---|
| 149 | }
|
---|
| 150 | else if (sBaselineShift == "sub")
|
---|
| 151 | {
|
---|
| 152 | shiftBy = -0.6F * textFontSize;
|
---|
| 153 | }
|
---|
| 154 | else if (sBaselineShift == "super")
|
---|
| 155 | {
|
---|
| 156 | shiftBy = 0.6F * textFontSize;
|
---|
| 157 | }
|
---|
| 158 | else if (sBaselineShift == "baseline")
|
---|
| 159 | {
|
---|
| 160 | shiftBy = 0;
|
---|
| 161 | }
|
---|
| 162 | else
|
---|
| 163 | {
|
---|
| 164 | shiftBy = SvgNumber.ParseNumber(sBaselineShift);
|
---|
| 165 | }
|
---|
| 166 | }
|
---|
| 167 |
|
---|
| 168 | foreach (XmlNode child in element.ChildNodes)
|
---|
| 169 | {
|
---|
| 170 | if (child.NodeType == XmlNodeType.Text)
|
---|
| 171 | {
|
---|
| 172 | ctp.Y -= shiftBy;
|
---|
| 173 | RenderTextPath(element, pathDrawing, GetText(element, child),
|
---|
| 174 | new Point(ctp.X, ctp.Y), rotate, placement);
|
---|
| 175 | ctp.Y += shiftBy;
|
---|
| 176 | }
|
---|
| 177 | }
|
---|
| 178 | }
|
---|
| 179 |
|
---|
| 180 | private void RenderTextPath(SvgTextContentElement element, WpfTextOnPathDrawing pathDrawing,
|
---|
| 181 | string text, Point origin, double rotate, WpfTextPlacement placement)
|
---|
| 182 | {
|
---|
| 183 | if (String.IsNullOrEmpty(text))
|
---|
| 184 | {
|
---|
| 185 | return;
|
---|
| 186 | }
|
---|
| 187 |
|
---|
| 188 | double emSize = GetComputedFontSize(element);
|
---|
| 189 | FontFamily fontFamily = GetTextFontFamily(element, emSize);
|
---|
| 190 |
|
---|
| 191 | FontStyle fontStyle = GetTextFontStyle(element);
|
---|
| 192 | FontWeight fontWeight = GetTextFontWeight(element);
|
---|
| 193 |
|
---|
| 194 | FontStretch fontStretch = GetTextFontStretch(element);
|
---|
| 195 |
|
---|
| 196 | WpfTextStringFormat stringFormat = GetTextStringFormat(element);
|
---|
| 197 |
|
---|
| 198 | // Fix the use of Postscript fonts...
|
---|
| 199 | WpfFontFamilyVisitor fontFamilyVisitor = _drawContext.FontFamilyVisitor;
|
---|
| 200 | if (!String.IsNullOrEmpty(_actualFontName) && fontFamilyVisitor != null)
|
---|
| 201 | {
|
---|
| 202 | WpfFontFamilyInfo currentFamily = new WpfFontFamilyInfo(fontFamily, fontWeight,
|
---|
| 203 | fontStyle, fontStretch);
|
---|
| 204 | WpfFontFamilyInfo familyInfo = fontFamilyVisitor.Visit(_actualFontName,
|
---|
| 205 | currentFamily, _drawContext);
|
---|
| 206 | if (familyInfo != null && !familyInfo.IsEmpty)
|
---|
| 207 | {
|
---|
| 208 | fontFamily = familyInfo.Family;
|
---|
| 209 | fontWeight = familyInfo.Weight;
|
---|
| 210 | fontStyle = familyInfo.Style;
|
---|
| 211 | fontStretch = familyInfo.Stretch;
|
---|
| 212 | }
|
---|
| 213 | }
|
---|
| 214 |
|
---|
| 215 | WpfSvgPaint fillPaint = new WpfSvgPaint(_drawContext, element, "fill");
|
---|
| 216 | Brush textBrush = fillPaint.GetBrush();
|
---|
| 217 |
|
---|
| 218 | WpfSvgPaint strokePaint = new WpfSvgPaint(_drawContext, element, "stroke");
|
---|
| 219 | Pen pen = strokePaint.GetPen();
|
---|
| 220 |
|
---|
| 221 | TextDecorationCollection textDecors = GetTextDecoration(element);
|
---|
| 222 | TextAlignment alignment = stringFormat.Alignment;
|
---|
| 223 |
|
---|
| 224 | pathDrawing.FontSize = emSize;
|
---|
| 225 |
|
---|
| 226 | pathDrawing.FontFamily = fontFamily;
|
---|
| 227 | pathDrawing.FontWeight = fontWeight;
|
---|
| 228 | pathDrawing.FontStretch = fontStretch;
|
---|
| 229 |
|
---|
| 230 | pathDrawing.Foreground = textBrush;
|
---|
| 231 |
|
---|
| 232 | pathDrawing.AddTextPath(text, origin);
|
---|
| 233 | }
|
---|
| 234 |
|
---|
| 235 | #endregion
|
---|
| 236 | }
|
---|
| 237 | }
|
---|