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); } }
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); } }
public SvgAnimatedLength(ISvgLength baseVal, ISvgLength animVal) { _baseVal = baseVal; _animVal = animVal; }
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 ISvgLength ReplaceItem(ISvgLength newItem, uint index) { return (ISvgLength) base.ReplaceItem(newItem, index); }
public SvgAnimatedLength(SvgElement ownerElement, string propertyName, SvgLengthDirection direction, string strValue, string defaultValue) { _baseVal = new SvgLength(ownerElement, propertyName, direction, strValue, defaultValue); _animVal = _baseVal; }
public ISvgLength Initialize(ISvgLength newItem) { return (ISvgLength) base.Initialize(newItem); }
public ISvgLength InsertItemBefore(ISvgLength newItem, uint index) { return (ISvgLength) base.InsertItemBefore(newItem, index); }
public ISvgLength AppendItem(ISvgLength newItem) { return (ISvgLength) base.AppendItem(newItem); }
public ISvgLength AppendItem(ISvgLength newItem) { return((ISvgLength)base.AppendItem(newItem)); }
public ISvgLength ReplaceItem(ISvgLength newItem, uint index) { return((ISvgLength)base.ReplaceItem(newItem, index)); }
public ISvgLength InsertItemBefore(ISvgLength newItem, uint index) { return((ISvgLength)base.InsertItemBefore(newItem, index)); }
public ISvgLength Initialize(ISvgLength newItem) { return((ISvgLength)base.Initialize(newItem)); }