public override void HandleAttributeChange(XmlAttribute attribute) { if (attribute.NamespaceURI.Length == 0) { // This list may be too long to be useful... switch (attribute.LocalName) { // Additional attributes case "x": x = null; return; case "y": y = null; return; case "width": width = null; return; case "height": height = null; return; } base.HandleAttributeChange(attribute); } }
public override void HandleAttributeChange(XmlAttribute attribute) { if (attribute.NamespaceURI.Length == 0) { switch (attribute.LocalName) { case "x": _x = null; return; case "y": _y = null; return; case "width": _width = null; return; case "height": _height = null; return; } } else if (attribute.NamespaceURI == SvgDocument.XLinkNamespace) { switch (attribute.LocalName) { case "href": _instanceRoot = null; break; } } base.HandleAttributeChange(attribute); }
public void RenderTextPath(DrawingContext dc, PathGeometry pathGeometry, TextAlignment pathAlignment) { if (_pathChars == null) { throw new InvalidOperationException(); } if (_pathChars.Count == 0) { return; } //ISvgAnimatedLength pathOffset = _svgElement.StartOffset; SvgTextPathMethod pathMethod = (SvgTextPathMethod)_textPathElement.Method.BaseVal; SvgTextPathSpacing pathSpacing = (SvgTextPathSpacing)_textPathElement.Spacing.BaseVal; ISvgAnimatedLength pathOffset = this.GetPathOffset(); if (pathOffset != null && pathOffset.AnimVal.Value < 0) { this.RenderEndAlignedText(dc, pathGeometry, pathOffset); } else { if (pathAlignment == TextAlignment.Right) { this.RenderEndAlignedText(dc, pathGeometry, pathOffset); } else { this.RenderStartAlignedText(dc, pathGeometry, pathOffset, pathAlignment); } } }
private void addRoundedRect(GraphicsPath graphicsPath, RectangleF rect, float rx, float ry) { if (rx == 0F) { rx = ry; } else if (ry == 0F) { ry = rx; } rx = Math.Min(rect.Width / 2, rx); ry = Math.Min(rect.Height / 2, ry); float a = rect.X + rect.Width - rx; graphicsPath.AddLine(rect.X + rx, rect.Y, a, rect.Y); graphicsPath.AddArc(a - rx, rect.Y, rx * 2, ry * 2, 270, 90); float right = rect.X + rect.Width; // rightmost X float b = rect.Y + rect.Height - ry; graphicsPath.AddLine(right, rect.Y + ry, right, b); graphicsPath.AddArc(right - rx * 2, b - ry, rx * 2, ry * 2, 0, 90); graphicsPath.AddLine(right - rx, rect.Y + rect.Height, rect.X + rx, rect.Y + rect.Height); graphicsPath.AddArc(rect.X, b - ry, rx * 2, ry * 2, 90, 90); graphicsPath.AddLine(rect.X, b, rect.X, rect.Y + ry); graphicsPath.AddArc(rect.X, rect.Y, rx * 2, ry * 2, 180, 90); }
public override void HandleAttributeChange(XmlAttribute attribute) { if (attribute.NamespaceURI.Length == 0) { switch (attribute.LocalName) { case "cx": _cx = null; Invalidate(); return; case "cy": _cy = null; Invalidate(); return; case "rx": _rx = null; Invalidate(); return; case "ry": _ry = null; Invalidate(); return; // Color.attrib, Paint.attrib case "color": case "fill": case "fill-rule": case "stroke": case "stroke-dasharray": case "stroke-dashoffset": case "stroke-linecap": case "stroke-linejoin": case "stroke-miterlimit": case "stroke-width": // Opacity.attrib case "opacity": case "stroke-opacity": case "fill-opacity": // Graphics.attrib case "display": case "image-rendering": case "shape-rendering": case "text-rendering": case "visibility": Invalidate(); break; case "transform": Invalidate(); break; } base.HandleAttributeChange(attribute); } }
public void DrawTextPath(DrawingContext dc, PathGeometry pathGeometry, ISvgAnimatedLength startOffset, TextAlignment alignment, SvgTextPathMethod method, SvgTextPathSpacing spacing) { if (alignment == TextAlignment.Right) { this.DrawEndAlignedTextPath(dc, pathGeometry, startOffset); } else { this.DrawStartAlignedTextPath(dc, pathGeometry, startOffset, alignment); } }
public void Resize() { // TODO: Invalidate! Fire SVGResize _x = null; _y = null; _width = null; _height = null; _currentView = null; _cachedViewBoxTransform = null; _viewport = null; _svgFitToViewBox = null; _svgFitToViewBox = new SvgFitToViewBox(this); if (this != OwnerDocument.RootElement) { (OwnerDocument.RootElement as SvgSvgElement).Resize(); } }
public void Resize() { // TODO: Invalidate! Fire SVGResize x = null; y = null; width = null; height = null; currentView = null; cachedViewBoxTransform = null; viewport = null; svgFitToViewBox = null; svgFitToViewBox = new SvgFitToViewBox(this); if (this == OwnerDocument.RootElement) { // TODO } else { (OwnerDocument.RootElement as SvgSvgElement).Resize(); } }
private ISvgAnimatedLength GetPathOffset() { ISvgAnimatedLength pathOffset = _textPathElement.StartOffset; if (pathOffset != null && pathOffset.AnimVal != null) { if (pathOffset.AnimVal.Value.Equals(0)) { var curOffset = _pathTextRuns[0].StartOffset; if (curOffset != null && curOffset.AnimVal != null) { if (!curOffset.AnimVal.Value.Equals(0)) { return(curOffset); } } } } return(pathOffset); }
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 override void HandleAttributeChange(XmlAttribute attribute) { if (attribute.NamespaceURI.Length == 0) { switch (attribute.LocalName) { case "x": x = null; Invalidate(); return; case "y": y = null; Invalidate(); return; case "width": width = null; Invalidate(); return; case "height": height = null; Invalidate(); return; case "rx": rx = null; Invalidate(); return; case "ry": ry = null; Invalidate(); return; // Color.attrib, Paint.attrib case "color": case "fill": case "fill-rule": case "stroke": case "stroke-dasharray": case "stroke-dashoffset": case "stroke-linecap": case "stroke-linejoin": case "stroke-miterlimit": case "stroke-width": // Opacity.attrib case "opacity": case "stroke-opacity": case "fill-opacity": // Graphics.attrib case "display": case "image-rendering": case "shape-rendering": case "text-rendering": case "visibility": Invalidate(); break; case "transform": Invalidate(); break; case "onclick": break; } base.HandleAttributeChange(attribute); } }
private void RenderEndAlignedText(DrawingContext dc, PathGeometry svgPath, ISvgAnimatedLength startOffset) { if (svgPath == null || svgPath.Figures == null || svgPath.Figures.Count != 1) { Debug.Assert(false, "Monitor invalid path cases in debug mode!"); return; } var pathFigure = svgPath.Figures[0]; _pathLength = WpfConvert.GetPathFigureLength(pathFigure); if (_pathLength.Equals(0) || _textLength.Equals(0)) { return; } double scalingFactor = 1.0; // Not scaling the text to fit... double progress = 1.0; if (startOffset != null && startOffset.AnimVal != null) { ISvgLength offsetLength = startOffset.AnimVal; if (offsetLength.Value < 0) { progress = 0; } switch (offsetLength.UnitType) { // If a percentage is given, then the startOffset represents a // percentage distance along the entire path. case SvgLengthType.Percentage: if (!offsetLength.ValueInSpecifiedUnits.Equals(0)) { progress += offsetLength.ValueInSpecifiedUnits / 100d; } break; // If a length other than a percentage is given, then the startOffset represents a distance along // the path measured in the current user coordinate system. case SvgLengthType.Number: progress += offsetLength.ValueInSpecifiedUnits / _pathLength; break; } } if (progress < 0) { progress *= -1; } if (progress > 1) { progress = progress - 1; while (progress > 1) { progress = progress - 1; } } PathGeometry pathGeometry = new PathGeometry(new PathFigure[] { pathFigure }); Point ptPrevPos = new Point(0, 0); int charCount = _pathChars.Count - 1; for (int i = charCount; i >= 0; i--) { var pathChar = _pathChars[i]; var pathTextRun = _pathTextRuns[pathChar.Index]; var textBuilder = pathTextRun.Builder; double width = scalingFactor * pathChar.Width; double baseline = scalingFactor * textBuilder.Baseline; progress -= width / 2 / _pathLength; if (progress < 0) { break; } Point ptNext, ptTangent; pathGeometry.GetPointAtFractionLength(progress, out ptNext, out ptTangent); if (i != charCount && AreEqual(ptNext, ptPrevPos)) { break; } var textPath = textBuilder.Build(pathTextRun.Element, pathChar.Text, pathChar.X, pathChar.Y); var textTransform = new TransformGroup(); textTransform.Children.Add(new RotateTransform(Math.Atan2(ptTangent.Y, ptTangent.X) * 180 / Math.PI, width / 2, baseline)); textTransform.Children.Add(new TranslateTransform(ptNext.X - width / 2, ptNext.Y - baseline)); var curTransform = textPath.Transform; if (curTransform != null && curTransform.Value.IsIdentity == false) { //Debug.Assert(false, "TODO: Wish to see the case"); textTransform.Children.Add(curTransform); } textPath.Transform = new MatrixTransform(textTransform.Value); pathTextRun.AddRun(textPath); progress -= width / 2 / _pathLength; ptPrevPos = ptNext; } foreach (var pathTextRun in _pathTextRuns) { pathTextRun.RenderRun(dc); } }
private void RenderStartAlignedText(DrawingContext dc, PathGeometry svgPath, ISvgAnimatedLength startOffset, TextAlignment alignment) { if (svgPath == null || svgPath.Figures == null || svgPath.Figures.Count != 1) { // Debug.Assert(false, "Monitor invalid path cases in debug mode!"); return; } var pathFigure = svgPath.Figures[0]; _pathLength = WpfConvert.GetPathFigureLength(pathFigure); if (_pathLength.Equals(0) || _textLength.Equals(0)) { return; } //double scalingFactor = pathLength / textLength; double scalingFactor = 1.0; // Not scaling the text to fit... double progress = 0; if (startOffset != null && startOffset.AnimVal != null) { ISvgLength offsetLength = startOffset.AnimVal; switch (offsetLength.UnitType) { // If a percentage is given, then the startOffset represents a // percentage distance along the entire path. case SvgLengthType.Percentage: if (!offsetLength.ValueInSpecifiedUnits.Equals(0)) { progress += offsetLength.ValueInSpecifiedUnits / 100d; } break; // If a length other than a percentage is given, then the startOffset represents a distance along // the path measured in the current user coordinate system. case SvgLengthType.Number: progress += offsetLength.ValueInSpecifiedUnits / _pathLength; break; } } PathGeometry pathGeometry = new PathGeometry(new PathFigure[] { pathFigure }); Point ptPrevPos = new Point(0, 0); double letterSpacing = 0; if (_textElement.LetterSpacing != null && _textElement.LetterSpacing.AnimVal != null) { letterSpacing = _textElement.LetterSpacing.AnimVal.ValueInSpecifiedUnits; } _pathLength += letterSpacing; var lengthFactor = 1.0; var textLength = this.GetTextLength(); if (textLength != null && textLength.AnimVal != null) { var textLengthValue = textLength.AnimVal.ValueInSpecifiedUnits; if (textLengthValue > 0) { lengthFactor = textLengthValue / _pathLength; // lengthFactor = _textLength / textLengthValue; // lengthFactor = textLengthValue / _textLength; // lengthFactor = _pathLength / textLengthValue; if (lengthFactor < 0.5) // Check for abuse! { lengthFactor = 1; } } } int charCount = _pathChars.Count; for (int i = 0; i < charCount; i++) { var pathChar = _pathChars[i]; var pathTextRun = _pathTextRuns[pathChar.Index]; var textBuilder = pathTextRun.Builder; double width = (scalingFactor * pathChar.Width * lengthFactor + letterSpacing); double baseline = scalingFactor * textBuilder.Baseline; progress += width / 2 / _pathLength; if (progress > 1) { break; } Point ptNextPos, ptTangent; pathGeometry.GetPointAtFractionLength(progress, out ptNextPos, out ptTangent); if (i != 0 && AreEqual(ptNextPos, ptPrevPos)) { break; } var textPath = textBuilder.Build(pathTextRun.Element, pathChar.Text, pathChar.X, pathChar.Y); var textTransform = new TransformGroup(); textTransform.Children.Add(new RotateTransform(Math.Atan2(ptTangent.Y, ptTangent.X) * 180 / Math.PI, width / 2, baseline)); textTransform.Children.Add(new TranslateTransform(ptNextPos.X - width / 2, ptNextPos.Y - baseline)); var curTransform = textPath.Transform; if (curTransform != null && curTransform.Value.IsIdentity == false) { textTransform.Children.Add(curTransform); } textPath.Transform = new MatrixTransform(textTransform.Value); pathTextRun.AddRun(textPath); progress += width / 2 / _pathLength; ptPrevPos = ptNextPos; } foreach (var pathTextRun in _pathTextRuns) { pathTextRun.RenderRun(dc); } }
public override void HandleAttributeChange(XmlAttribute attribute) { if (attribute.NamespaceURI.Length == 0) { // This list may be too long to be useful... switch (attribute.LocalName) { // Additional attributes case "x": x = null; return; case "y": y = null; return; case "width": width = null; return; case "height": height = null; return; } base.HandleAttributeChange(attribute); } }
private void DrawEndAlignedTextPath(DrawingContext dc, PathGeometry pathGeometry, ISvgAnimatedLength startOffset) { if (pathGeometry == null || pathGeometry.Figures == null || pathGeometry.Figures.Count != 1) { return; } _pathLength = GetPathFigureLength(pathGeometry.Figures[0]); if (_pathLength == 0 || _textLength == 0) return; //double scalingFactor = pathLength / textLength; double scalingFactor = 1.0; // Not scaling the text to fit... double progress = 1.0; //PathGeometry pathGeometry = // new PathGeometry(new PathFigure[] { PathFigure }); Point ptOld = new Point(0, 0); int itemCount = _formattedChars.Count - 1; for (int i = itemCount; i >= 0; i--) { FormattedText formText = _formattedChars[i]; double width = scalingFactor * formText.WidthIncludingTrailingWhitespace; double baseline = scalingFactor * formText.Baseline; progress -= width / 2 / _pathLength; Point point, tangent; pathGeometry.GetPointAtFractionLength(progress, out point, out tangent); if (i != itemCount) { if (point == ptOld) { break; } } dc.PushTransform( new TranslateTransform(point.X - width / 2, point.Y - baseline)); dc.PushTransform( new RotateTransform(Math.Atan2(tangent.Y, tangent.X) * 180 / Math.PI, width / 2, baseline)); //dc.PushTransform( // new ScaleTransform(scalingFactor, scalingFactor)); dc.DrawText(formText, _formattedOrigins[i]); dc.Pop(); dc.Pop(); //dc.Pop(); progress -= width / 2 / _pathLength; ptOld = point; } }
private void DrawStartAlignedTextPath(DrawingContext dc, PathGeometry pathGeometry, ISvgAnimatedLength startOffset, TextAlignment alignment) { if (pathGeometry == null || pathGeometry.Figures == null || pathGeometry.Figures.Count != 1) { return; } _pathLength = GetPathFigureLength(pathGeometry.Figures[0]); if (_pathLength == 0 || _textLength == 0) return; //double scalingFactor = pathLength / textLength; double scalingFactor = 1.0; // Not scaling the text to fit... double progress = 0; if (startOffset != null) { ISvgLength offsetLength = startOffset.AnimVal; if (offsetLength != null) { switch (offsetLength.UnitType) { case SvgLengthType.Percentage: if ((float)offsetLength.ValueInSpecifiedUnits != 0) { progress += offsetLength.ValueInSpecifiedUnits / 100d; } break; } } } //PathGeometry pathGeometry = // new PathGeometry(new PathFigure[] { PathFigure }); Point ptOld = new Point(0, 0); for (int i = 0; i < _formattedChars.Count; i++) { FormattedText formText = _formattedChars[i]; double width = scalingFactor * formText.WidthIncludingTrailingWhitespace; double baseline = scalingFactor * formText.Baseline; progress += width / 2 / _pathLength; Point point, tangent; pathGeometry.GetPointAtFractionLength(progress, out point, out tangent); if (i != 0) { if (point == ptOld) { break; } } dc.PushTransform( new TranslateTransform(point.X - width / 2, point.Y - baseline)); dc.PushTransform( new RotateTransform(Math.Atan2(tangent.Y, tangent.X) * 180 / Math.PI, width / 2, baseline)); //dc.PushTransform( // new ScaleTransform(scalingFactor, scalingFactor)); dc.DrawText(formText, _formattedOrigins[i]); dc.Pop(); dc.Pop(); //dc.Pop(); progress += width / 2 / _pathLength; ptOld = point; } }
public void DrawTextPath(DrawingContext dc, PathGeometry pathGeometry, ISvgAnimatedLength startOffset, TextAlignment alignment, SvgTextPathMethod method, SvgTextPathSpacing spacing) { if (alignment == TextAlignment.Right) { this.DrawEndAlignedTextPath(dc, pathGeometry, startOffset); } else { this.DrawStartAlignedTextPath(dc, pathGeometry, startOffset, alignment); } }
private void DrawEndAlignedTextPath(DrawingContext dc, PathGeometry pathGeometry, ISvgAnimatedLength startOffset) { if (pathGeometry == null || pathGeometry.Figures == null || pathGeometry.Figures.Count != 1) { return; } _pathLength = GetPathFigureLength(pathGeometry.Figures[0]); if (_pathLength == 0 || _textLength == 0) { return; } //double scalingFactor = pathLength / textLength; double scalingFactor = 1.0; // Not scaling the text to fit... double progress = 1.0; //PathGeometry pathGeometry = // new PathGeometry(new PathFigure[] { PathFigure }); Point ptOld = new Point(0, 0); int itemCount = _formattedChars.Count - 1; for (int i = itemCount; i >= 0; i--) { FormattedText formText = _formattedChars[i]; double width = scalingFactor * formText.WidthIncludingTrailingWhitespace; double baseline = scalingFactor * formText.Baseline; progress -= width / 2 / _pathLength; Point point, tangent; pathGeometry.GetPointAtFractionLength(progress, out point, out tangent); if (i != itemCount) { if (point == ptOld) { break; } } dc.PushTransform( new TranslateTransform(point.X - width / 2, point.Y - baseline)); dc.PushTransform( new RotateTransform(Math.Atan2(tangent.Y, tangent.X) * 180 / Math.PI, width / 2, baseline)); //dc.PushTransform( // new ScaleTransform(scalingFactor, scalingFactor)); dc.DrawText(formText, _formattedOrigins[i]); dc.Pop(); dc.Pop(); //dc.Pop(); progress -= width / 2 / _pathLength; ptOld = point; } }
private void addRoundedRect(GraphicsPath graphicsPath, RectangleF rect, float rx, float ry) { if(rx == 0F) rx = ry; else if(ry == 0F) ry = rx; rx = Math.Min(rect.Width/2, rx); ry = Math.Min(rect.Height/2, ry); float a = rect.X + rect.Width - rx; graphicsPath.AddLine(rect.X + rx, rect.Y, a, rect.Y); graphicsPath.AddArc(a-rx, rect.Y, rx*2, ry*2, 270, 90); float right = rect.X + rect.Width; // rightmost X float b = rect.Y + rect.Height - ry; graphicsPath.AddLine(right, rect.Y + ry, right, b); graphicsPath.AddArc(right - rx*2, b-ry, rx*2, ry*2, 0, 90); graphicsPath.AddLine(right - rx, rect.Y + rect.Height, rect.X + rx, rect.Y + rect.Height); graphicsPath.AddArc(rect.X, b-ry, rx*2, ry*2, 90, 90); graphicsPath.AddLine(rect.X, b, rect.X, rect.Y + ry); graphicsPath.AddArc(rect.X, rect.Y, rx*2, ry*2, 180, 90); }
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; } PathGeometry pathGeometry = CreateGeometry(targetPath, true) as PathGeometry; if (pathGeometry == null) { return; } this.IsTextPath = true; WpfTextOnPathDrawing pathDrawing = new WpfTextOnPathDrawing(); pathDrawing.BeginTextPath(); XmlNodeType nodeType = XmlNodeType.None; foreach (XmlNode child in textPath.ChildNodes) { nodeType = child.NodeType; if (nodeType == XmlNodeType.Text) { RenderTextPath(textPath, pathDrawing, GetText(textPath, child), new Point(ctp.X, ctp.Y), rotate, placement); } else if (nodeType == XmlNodeType.Element) { string nodeName = child.Name; if (string.Equals(nodeName, "tref")) { RenderTRefPath((SvgTRefElement)child, pathDrawing, ref ctp); } else if (string.Equals(nodeName, "tspan")) { RenderTSpanPath((SvgTSpanElement)child, pathDrawing, ref ctp); } } } WpfTextStringFormat stringFormat = GetTextStringFormat(_textElement); ISvgAnimatedLength pathOffset = textPath.StartOffset; SvgTextPathMethod pathMethod = (SvgTextPathMethod)textPath.Method.BaseVal; SvgTextPathSpacing pathSpacing = (SvgTextPathSpacing)textPath.Spacing.BaseVal; pathDrawing.DrawTextPath(_textContext, pathGeometry, pathOffset, stringFormat.Alignment, pathMethod, pathSpacing); pathDrawing.EndTextPath(); }
public override void HandleAttributeChange(XmlAttribute attribute) { if(attribute.NamespaceURI.Length == 0) { switch(attribute.LocalName) { case "x1": x1 = null; Invalidate(); return; case "y1": y1 = null; Invalidate(); return; case "x2": x2 = null; Invalidate(); return; case "y2": y2 = null; Invalidate(); return; case "marker-start": case "marker-mid": case "marker-end": // Color.attrib, Paint.attrib case "color": case "fill": case "fill-rule": case "stroke": case "stroke-dasharray": case "stroke-dashoffset": case "stroke-linecap": case "stroke-linejoin": case "stroke-miterlimit": case "stroke-width": // Opacity.attrib case "opacity": case "stroke-opacity": case "fill-opacity": // Graphics.attrib case "display": case "image-rendering": case "shape-rendering": case "text-rendering": case "visibility": Invalidate(); break; case "transform": Invalidate(); break; } base.HandleAttributeChange(attribute); } }
public override void HandleAttributeChange(XmlAttribute attribute) { if (attribute.NamespaceURI.Length == 0) { switch (attribute.LocalName) { case "x": x = null; return; case "y": y = null; return; case "width": width = null; return; case "height": height = null; return; } } else if (attribute.NamespaceURI == SvgDocument.XLinkNamespace) { switch (attribute.LocalName) { case "href": instanceRoot = null; break; } } base.HandleAttributeChange(attribute); }
public void Resize() { // TODO: Invalidate! Fire SVGResize x = null; y = null; width = null; height = null; currentView = null; cachedViewBoxTransform = null; viewport = null; svgFitToViewBox = null; svgFitToViewBox = new SvgFitToViewBox(this); if (this == OwnerDocument.RootElement) { // TODO } else { (OwnerDocument.RootElement as SvgSvgElement).Resize(); } }
private void DrawStartAlignedTextPath(DrawingContext dc, PathGeometry pathGeometry, ISvgAnimatedLength startOffset, TextAlignment alignment) { if (pathGeometry == null || pathGeometry.Figures == null || pathGeometry.Figures.Count != 1) { return; } _pathLength = GetPathFigureLength(pathGeometry.Figures[0]); if (_pathLength == 0 || _textLength == 0) { return; } //double scalingFactor = pathLength / textLength; double scalingFactor = 1.0; // Not scaling the text to fit... double progress = 0; if (startOffset != null) { ISvgLength offsetLength = startOffset.AnimVal; if (offsetLength != null) { switch (offsetLength.UnitType) { case SvgLengthType.Percentage: if ((float)offsetLength.ValueInSpecifiedUnits != 0) { progress += offsetLength.ValueInSpecifiedUnits / 100d; } break; } } } //PathGeometry pathGeometry = // new PathGeometry(new PathFigure[] { PathFigure }); Point ptOld = new Point(0, 0); for (int i = 0; i < _formattedChars.Count; i++) { FormattedText formText = _formattedChars[i]; double width = scalingFactor * formText.WidthIncludingTrailingWhitespace; double baseline = scalingFactor * formText.Baseline; progress += width / 2 / _pathLength; Point point, tangent; pathGeometry.GetPointAtFractionLength(progress, out point, out tangent); if (i != 0) { if (point == ptOld) { break; } } dc.PushTransform( new TranslateTransform(point.X - width / 2, point.Y - baseline)); dc.PushTransform( new RotateTransform(Math.Atan2(tangent.Y, tangent.X) * 180 / Math.PI, width / 2, baseline)); //dc.PushTransform( // new ScaleTransform(scalingFactor, scalingFactor)); dc.DrawText(formText, _formattedOrigins[i]); dc.Pop(); dc.Pop(); //dc.Pop(); progress += width / 2 / _pathLength; ptOld = point; } }
public override void HandleAttributeChange(XmlAttribute attribute) { if (attribute.NamespaceURI.Length == 0) { switch (attribute.LocalName) { case "x1": _x1 = null; Invalidate(); return; case "y1": _y1 = null; Invalidate(); return; case "x2": _x2 = null; Invalidate(); return; case "y2": _y2 = null; Invalidate(); return; case "marker-start": case "marker-mid": case "marker-end": // Color.attrib, Paint.attrib case CssConstants.PropColor: case "fill": case "fill-rule": case "stroke": case "stroke-dasharray": case "stroke-dashoffset": case "stroke-linecap": case "stroke-linejoin": case "stroke-miterlimit": case "stroke-width": // Opacity.attrib case "opacity": case "stroke-opacity": case "fill-opacity": // Graphics.attrib case CssConstants.PropDisplay: case "image-rendering": case "shape-rendering": case "text-rendering": case CssConstants.PropVisibility: Invalidate(); break; case "transform": Invalidate(); break; } base.HandleAttributeChange(attribute); } }
public void SetPosition(Point pos, SvgTextPathElement pathElement, SvgTextBaseElement textElement) { _contentPos = pos; _startOffset = this.GetStartOffset(pathElement, textElement); }