Example #1
0
 public static Point[] ComparePoints(PathGeometry user, PathGeometry target, double progress)
 {
     Point pU, pT1, pT2, tU, tT1, tT2;
     user.GetPointAtFractionLength(progress, out pU, out tU);
     target.GetPointAtFractionLength(progress, out pT1, out tT1);
     target.GetPointAtFractionLength(1-progress, out pT2, out tT2);
     return new[] {pU, pT1, pT2};
 }
Example #2
0
        //Size newArrangeOverride(Size finalSize)
        protected override Size ArrangeOverride(Size finalSize)
        {
            var bezier = new QuadraticBezierSegment(InnerPoint, new Point(finalSize.Width, finalSize.Height), true);
            var pathFigure = new PathFigure(new Point(10, 10), new[] { bezier }, false);

            var pathLength = TextOnPathBase.GetPathFigureLength(pathFigure);
            var neededSpace = 0.0; // finalSize.Width;


            foreach (UIElement child in Children)
            {
                //child.Measure(new Size(Double.PositiveInfinity,
                //                       Double.PositiveInfinity));
                neededSpace += child.DesiredSize.Width;
            }

            if (!pathLength.Equals(0.0) && !neededSpace.Equals(0.0) && !finalSize.Width.Equals(0.0))
            {
                var spaceAvail = pathLength - neededSpace;
                var spaceStep = spaceAvail / Children.Count;
                var stepPerc = spaceStep / spaceAvail;

                var scalingFactor = pathLength / neededSpace;
                var pathGeometry = new PathGeometry(new[] {pathFigure});
                var baseline = scalingFactor;

                var progress = 0.0; // stepPerc / 2;

                foreach (UIElement element in Children)
                {
                    var width = /*scalingFactor**/element.DesiredSize.Width;
                    progress += stepPerc / 2;

                    Point point, tangent;
                    pathGeometry.GetPointAtFractionLength(progress,
                                                          out point, out tangent);

                    var transformGroup = new TransformGroup();

                    //transformGroup.Children.Add(
                    //    new ScaleTransform(scalingFactor, scalingFactor));
                    transformGroup.Children.Add(
                        new RotateTransform(Math.Atan2(tangent.Y, tangent.X)
                                                *180/Math.PI, width/2, baseline));
                    //transformGroup.Children.Add(
                    //    new TranslateTransform(point.X - width / 2,
                    //                           point.Y - baseline));

                    element.RenderTransform = transformGroup;

                    element.Arrange(new Rect(point.X, point.Y, element.DesiredSize.Width, element.DesiredSize.Height));

                    progress += stepPerc / 2;
                }
            }
            return base.ArrangeOverride(finalSize);
        }
 private Point GetPosition(double value, EllipseGeometry geometry)
 {
     var pathGeometry = geometry.GetOutlinedPathGeometry();
     if (pathGeometry.Figures.Count == 0)
         return geometry.Center;
     var outherGeometry = new PathGeometry(new[] { pathGeometry.Figures[0] });
     Point outherPoint, outherTangent;
     outherGeometry.GetPointAtFractionLength(value, out outherPoint, out outherTangent);
     return outherPoint;
 }
Example #4
0
        // Create an ESRI polyline based on a densified representation of WPFs ArcSegment
        public static ESRI.ArcGIS.Client.Geometry.Polyline ConstructArcSegment(ESRI.ArcGIS.Client.Geometry.MapPoint startPoint, ESRI.ArcGIS.Client.Geometry.MapPoint endPoint, double radius, bool isMinor, SweepDirection direction)
        {
            if (endPoint == null)
            return null;

              // WPF ArcSegment has issue with high coordinates values.
              // Bring coordinates down to 0,0 and translate back to real world later.

              double startX = startPoint.X;
              double startY = startPoint.Y;

              double absRadius = Math.Abs(radius);

              // We need to switch the curve direction, b/c we are starting with the end point
              if (radius > 0)
            direction = direction == SweepDirection.Clockwise ? SweepDirection.Counterclockwise : SweepDirection.Clockwise;

              Size radiusAspect = new Size(absRadius, absRadius);
              Point myEndPoint = new Point(endPoint.X - startX, endPoint.Y - startY);

              bool isLargeArc = !isMinor;
              ArcSegment wpfArcSegment = new ArcSegment(myEndPoint, radiusAspect, 0, isLargeArc, direction, false);

              // compose one or more segments into a collection
              var pathcoll = new PathSegmentCollection();
              pathcoll.Add(wpfArcSegment);

              // create a figure based on the set of segments
              var pathFigure = new PathFigure();
              pathFigure.Segments = pathcoll;
              pathFigure.IsClosed = false;

              // compose a collection of figures
              var figureCollection = new PathFigureCollection();
              figureCollection.Add(pathFigure);

              // create a path-geometry using the figures collection
              var geometryPath = new PathGeometry(figureCollection);

              ESRI.ArcGIS.Client.Geometry.PointCollection pointCollection = new ESRI.ArcGIS.Client.Geometry.PointCollection();

              double numSegments = 1.0 / 50;        // Default 50
              Point point, tangent;

              Point pointA, pointB;
              geometryPath.GetPointAtFractionLength(0, out pointA, out tangent);
              geometryPath.GetPointAtFractionLength(numSegments, out pointB, out tangent);
              double partDistance = LineLength(pointA.X, pointA.Y, pointB.X, pointB.Y);
              if (partDistance > 1.0)
            numSegments /= partDistance;
              if (1 / numSegments > 160)            // cap it at 160 vertexes
            numSegments = 1.0 / 160;            // Server is having issue with 185+ vertexes (180 seems ok)

              for (double fraction = 0.0; fraction < 1.0; fraction += numSegments)
              {
            geometryPath.GetPointAtFractionLength(fraction, out point, out tangent);
            pointCollection.Add(new ESRI.ArcGIS.Client.Geometry.MapPoint(point.X + startX, point.Y + startY));
              }
              pointCollection.Add(endPoint);  // faction 1 can be skipped, so add it here.

              ESRI.ArcGIS.Client.Geometry.Polyline polyline = new ESRI.ArcGIS.Client.Geometry.Polyline();
              polyline.Paths.Add(pointCollection);

              return polyline;
        }
Example #5
0
        /// <summary>
        /// Positionates each child in an arc line form depending on the Bend and amount of child controls.
        /// </summary>
        /// <param name="finalSize">The maximum possible space given by the parent control.</param>
        /// <returns>The calculated needed space in sum of all available child controls.</returns>
        protected override Size ArrangeOverride(Size finalSize)
        {
            if (InternalChildren.Count <= 0 || !(finalSize.Width > 0))
                return base.ArrangeOverride(finalSize);

            ResetArc(finalSize);

            var pathLength = PathCalculator.GetPathFigureLength(_figure);
            var pathGeometry = new PathGeometry(new PathFigure[] { _figure });
            var distance = (double)1 / (double)(InternalChildren.Count + 1);
            var position = distance;
            foreach (UIElement child in InternalChildren)
            {
                Point point, tangent;
                pathGeometry.GetPointAtFractionLength(position, out point, out tangent);

                Size childSize = child.DesiredSize;
                point.X -= childSize.Width / 2;
                point.Y -= childSize.Height;
                child.Arrange(new Rect(point, childSize));

                if (RotateElements)
                {
                    var elementCenter = new Size(childSize.Width / 2, childSize.Height / 2);
                    var transforms = new TransformGroup();
                    transforms.Children.Add(new RotateTransform((Math.Atan2(tangent.Y, tangent.X)
                                                                 * 180
                                                                 / Math.PI),
                        elementCenter.Width,
                        elementCenter.Height));
                    child.RenderTransform = transforms;
                }
                else
                    child.RenderTransform = null;
                    
                position += distance;
            }
            return base.ArrangeOverride(finalSize);
        }
Example #6
0
        //protected override Size ArrangeOverride(Size finalSize)
        Size OriginalArrangeOverride(Size finalSize)
        {
            var pathLength = TextOnPathBase.GetPathFigureLength(PathFigure);
            var textLength = 0.0; // finalSize.Width;


            foreach (UIElement child in Children)
            {
                //child.Measure(new Size(Double.PositiveInfinity,
                //                       Double.PositiveInfinity));
                textLength += child.DesiredSize.Width;
            }

            if (!pathLength.Equals(0.0) && !textLength.Equals(0.0) && !finalSize.Width.Equals(0.0))
            {
                var scalingFactor = pathLength/textLength;
                var pathGeometry = new PathGeometry(new PathFigure[] {PathFigure});
                var baseline = scalingFactor;
                var progress = 0.0;

                foreach (UIElement element in Children)
                {
                    var width = scalingFactor*element.DesiredSize.Width;
                    progress += width/2/pathLength;
                    Point point, tangent;

                    pathGeometry.GetPointAtFractionLength(progress,
                                                          out point, out tangent);

                    var transformGroup = new TransformGroup();

                    //transformGroup.Children.Add(
                    //    new ScaleTransform(scalingFactor, scalingFactor));
                    transformGroup.Children.Add(
                        new RotateTransform(Math.Atan2(tangent.Y, tangent.X)
                                                *180/Math.PI, width/2, baseline));
                    //transformGroup.Children.Add(
                    //    new TranslateTransform(point.X - width / 2,
                    //                           point.Y - baseline));

                    element.RenderTransform = transformGroup;

                    element.Arrange(new Rect(point.X, point.Y, element.DesiredSize.Width, element.DesiredSize.Height));

                    progress += width/2/pathLength;
                }
            }
            return base.ArrangeOverride(finalSize);
        }
Example #7
0
        void OrientTextOnPath()
        {
            var pathLength = TextOnPathBase.GetPathFigureLength(PathFigure);
            var textLength = 0.0;

            foreach (UIElement child in _mainPanel.Children)
            {
                child.Measure(new Size(Double.PositiveInfinity,
                                       Double.PositiveInfinity));
                textLength += child.DesiredSize.Width;
            }

            if (pathLength == 0 || textLength == 0)
                return;

            var scalingFactor = pathLength / textLength;
            var pathGeometry = new PathGeometry(new PathFigure[] { PathFigure });
            var baseline = scalingFactor * Fontsize * FontFamily.Baseline;
            var progress = 0.0;

            foreach (UIElement child in _mainPanel.Children)
            {
                var width = scalingFactor * child.DesiredSize.Width;
                progress += width / 2 / pathLength;
                Point point, tangent;

                pathGeometry.GetPointAtFractionLength(progress,
                                                out point, out tangent);

                var transformGroup = new TransformGroup();

                transformGroup.Children.Add(
                    new ScaleTransform(scalingFactor, scalingFactor));
                transformGroup.Children.Add(
                    new RotateTransform(Math.Atan2(tangent.Y, tangent.X)
                        * 180 / Math.PI, width / 2, baseline));
                transformGroup.Children.Add(
                    new TranslateTransform(point.X - width / 2,
                                           point.Y - baseline));

                child.RenderTransform = transformGroup;
                progress += width / 2 / pathLength;
            }
        }
Example #8
0
        /// <summary>
        /// Positionates each child in an ellipse form depending on the amount of child controls.
        /// </summary>
        /// <param name="finalSize">The maximum possible space given by the parent control.</param>
        /// <returns>The calculated needed space in sum of all available child controls.</returns>
        protected override Size ArrangeOverride(Size finalSize)
        {
            if (finalSize.Height <= 0 ||
                finalSize.Width <= 0)
                return finalSize;

            if (InternalChildren.Count <= 0)
                return base.ArrangeOverride(finalSize);

            ResetEllipse(finalSize);

            var figure = _ellipse.GetOutlinedPathGeometry().Figures[0];
            var pathGeometry = new PathGeometry(new[] { figure });

            var points = new List<Point>();
            var tangents = new List<Point>();
            var distance = (double)1 / (double)InternalChildren.Count;
            var position = GetElementStartPositionValue();
            foreach (var child in InternalChildren)
            {
                Point point, tangent;
                pathGeometry.GetPointAtFractionLength(position, out point, out tangent);
                points.Add(point);
                tangents.Add(tangent);
                position += distance;
                if (position > 1)
                    position -= 1;
            }

            if (EllipseRotateDirection == SweepDirection.Counterclockwise)
            {
                points.Reverse();
                tangents.Reverse();
                var point = points.Last();
                points.Remove(point);
                points.Insert(0, point);

                var tangent = tangents.Last();
                tangents.Remove(tangent);
                tangents.Insert(0, tangent);
            }

            int pos = 0;
            foreach (UIElement child in InternalChildren)
            {
                var childSize = child.DesiredSize;
                var elementPos = points[pos];
                elementPos.X -= childSize.Width / 2;
                elementPos.Y -= childSize.Height / 2;
                child.SnapsToDevicePixels = true;
                child.Arrange(new Rect(elementPos, childSize));
                if (RotateElements)
                {
                    var elementCenter = new Size(childSize.Width / 2, childSize.Height / 2);
                    var transforms = new TransformGroup();

                    var centerPoint = new Point(finalSize.Width / 2, finalSize.Height / 2);
                    var angle = CalculatePileToPlayerAngle(elementPos, centerPoint);
                    transforms.Children.Add(new RotateTransform(angle, elementCenter.Width, elementCenter.Height));

                    //transforms.Children.Add(new RotateTransform((Math.Atan2(tangents[pos].Y, tangents[pos].X)
                    //                                                * 180
                    //                                                / Math.PI)
                    //                                                + GetElementsRotateDirectionValue(),
                    //                                            elementCenter.Width,
                    //                                            elementCenter.Height));
                    child.RenderTransform = transforms;
                }
                else
                    child.RenderTransform = null;
                ++pos;
            }
            return base.ArrangeOverride(finalSize);
        }
        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;
            }
        }
        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 OrientTextOnPath()
		{
			double pathFigureLength = TextOnPathBase.GetPathFigureLength(this.PathFigure);
			double num = 0.0;
			foreach (UIElement uIElement in this.mainPanel.Children)
			{
				uIElement.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
				num += uIElement.DesiredSize.Width;
			}
			if (pathFigureLength != 0.0 && num != 0.0)
			{
				double num2 = pathFigureLength / num;
				PathGeometry pathGeometry = new PathGeometry(new PathFigure[]
				{
					this.PathFigure
				});
				double num3 = num2 * 100.0 * base.FontFamily.Baseline;
				double num4 = 0.0;
				foreach (UIElement uIElement in this.mainPanel.Children)
				{
					double num5 = num2 * uIElement.DesiredSize.Width;
					num4 += num5 / 2.0 / pathFigureLength;
					Point point;
					Point point2;
					pathGeometry.GetPointAtFractionLength(num4, out point, out point2);
					uIElement.RenderTransform = new TransformGroup
					{
						Children = 
						{
							new ScaleTransform(num2, num2),
							new RotateTransform(Math.Atan2(point2.Y, point2.X) * 180.0 / 3.1415926535897931, num5 / 2.0, num3),
							new TranslateTransform(point.X - num5 / 2.0, point.Y - num3)
						}
					};
					num4 += num5 / 2.0 / pathFigureLength;
				}
			}
		}
Example #12
0
        protected virtual void TransformVisualChildren()
            {
            this.measureRect = new Rect();
            this.ContentRect = RectangleD.Empty;

            if (this.pathLength == 0 || this.textLength == 0 || this.textHeight == 0)
                return;

            if (this.formattedChars.Count != this.visualChildren.Count)
                return;

            double scalingFactor;
            double fontSize = this.FontSize;
            if (fontSize.IsFinite() && fontSize > 0)
                {
                // Scale to particular height, but not longer than the path
                scalingFactor = Math.Min(fontSize / this.textHeight, this.pathLength / this.textLength);
                }
            else
                {
                // Scale to the length of the path
                scalingFactor = this.pathLength / this.textLength;
                }

            PathGeometry pathGeometry = new PathGeometry(new PathFigure[] { PathFigure });
            
            // If we're not scaled to the full path length, then center in what we do use
            double progressFraction = ((this.pathLength - this.textLength * scalingFactor) / 2) / this.pathLength;

            for (int index = 0; index < visualChildren.Count; index++)
                {
                FormattedText formText  = this.formattedChars[index];
                double        width     = scalingFactor * formText.WidthIncludingTrailingWhitespace;
                double        height    = scalingFactor * (formText.Height);
                double        baseline  = scalingFactor * formText.Baseline;

                progressFraction += width / 2 / this.pathLength;

                Point point, tangent;
                pathGeometry.GetPointAtFractionLength(progressFraction, out point, out tangent);

                DrawingVisual       drawingVisual      = this.visualChildren[index] as DrawingVisual;
                TransformGroup      transformGroup     = drawingVisual.Transform    as TransformGroup;
                ScaleTransform      scaleTransform     = transformGroup.Children[0] as ScaleTransform;
                RotateTransform     rotateTransform    = transformGroup.Children[1] as RotateTransform;
                TranslateTransform  translateTransform = transformGroup.Children[2] as TranslateTransform;

                scaleTransform.ScaleX   = scalingFactor;
                scaleTransform.ScaleY   = scalingFactor;
                rotateTransform.Angle   = Math.Atan2(tangent.Y, tangent.X) * 180 / Math.PI;
                rotateTransform.CenterX = width / 2;
                rotateTransform.CenterY = baseline;
                translateTransform.X    = point.X - width / 2;
                translateTransform.Y    = this.FontVerticallyCentered ? (point.Y - height / 2 - this.FontBaseline) : (point.Y - baseline - this.FontBaseline);

                Rect rc = drawingVisual.ContentBounds;
                rc.Transform(transformGroup.Value);

                this.ContentRect = this.ContentRect.UnionD(new RectangleD(rc));
                this.measureRect.Union(rc);

                progressFraction += width / 2 / pathLength;
                }

            InvalidateMeasure();
            }
        void WarpAllPoints(PathGeometry warpedTextPathGeometry, PathGeometry flattenedTextPathGeometry)
        {
            PathGeometry pathGeometry = new PathGeometry(new PathFigure[] { PathFigure });
            double scalingFactor = pathLength / textLength;

            LoopThroughAllFlattenedPathPoints(warpedTextPathGeometry, flattenedTextPathGeometry, delegate(Point pointSrc)
            {
                double fractionLength = Math.Max(0, Math.Min(1, pointSrc.X / textLength));
                double offsetFromBaseline = scalingFactor * (baseline - pointSrc.Y);
                Point pathPoint, pathTangent;

                pathGeometry.GetPointAtFractionLength(fractionLength, out pathPoint, out pathTangent);
                double angle = Math.Atan2(pathTangent.Y, pathTangent.X);

                Point pointDst = new Point();
                pointDst.X = pathPoint.X + offsetFromBaseline * Math.Sin(angle);
                pointDst.Y = pathPoint.Y - offsetFromBaseline * Math.Cos(angle);

                return pointDst;
            });

            if (ShiftToOrigin)
            {
                Rect boundsRect = warpedTextPathGeometry.Bounds;

                LoopThroughAllFlattenedPathPoints(warpedTextPathGeometry, warpedTextPathGeometry, delegate(Point pointSrc)
                {
                    Point pointDst = new Point();
                    pointDst.X = pointSrc.X - boundsRect.Left;
                    pointDst.Y = pointSrc.Y - boundsRect.Top;
                    return pointDst;
                });
            }
        }
        protected virtual void TransformVisualChildren()
        {
            boundingRect = new Rect();

            if (pathLength == 0 || textLength == 0)
                return;

            if (formattedChars.Count != visualChildren.Count)
                return;

            double scalingFactor = pathLength / textLength;
            PathGeometry pathGeometry =
                new PathGeometry(new PathFigure[] { PathFigure });
            double progress = 0;
            boundingRect = new Rect();

            for (int index = 0; index < visualChildren.Count; index++)
            {
                FormattedText formText = formattedChars[index];
                double width = scalingFactor *
                            formText.WidthIncludingTrailingWhitespace;
                double baseline = scalingFactor * formText.Baseline;
                progress += width / 2 / pathLength;
                Point point, tangent;
                pathGeometry.GetPointAtFractionLength(progress,
                                            out point, out tangent);

                DrawingVisual drawingVisual =
                    visualChildren[index] as DrawingVisual;
                TransformGroup transformGroup =
                    drawingVisual.Transform as TransformGroup;
                ScaleTransform scaleTransform =
                    transformGroup.Children[0] as ScaleTransform;
                RotateTransform rotateTransform =
                    transformGroup.Children[1] as RotateTransform;
                TranslateTransform translateTransform =
                    transformGroup.Children[2] as TranslateTransform;

                scaleTransform.ScaleX = scalingFactor;
                scaleTransform.ScaleY = scalingFactor;
                rotateTransform.Angle =
                    Math.Atan2(tangent.Y, tangent.X) * 180 / Math.PI;
                rotateTransform.CenterX = width / 2;
                rotateTransform.CenterY = baseline;
                translateTransform.X = point.X - width / 2;
                translateTransform.Y = point.Y - baseline;

                Rect rect = drawingVisual.ContentBounds;
                rect.Transform(transformGroup.Value);
                boundingRect.Union(rect);

                progress += width / 2 / pathLength;
            }
            InvalidateMeasure();
        }
		protected virtual void TransformVisualChildren()
		{
			this.boundingRect = default(Rect);
			if (this.pathLength != 0.0 && this.textLength != 0.0)
			{
				if (this.formattedChars.Count == this.visualChildren.Count)
				{
					double num = this.pathLength / this.textLength;
					PathGeometry pathGeometry = new PathGeometry(new PathFigure[]
					{
						base.PathFigure
					});
					double num2 = 0.0;
					this.boundingRect = default(Rect);
					for (int i = 0; i < this.visualChildren.Count; i++)
					{
						FormattedText formattedText = this.formattedChars[i];
						double num3 = num * formattedText.WidthIncludingTrailingWhitespace;
						double num4 = num * formattedText.Baseline;
						num2 += num3 / 2.0 / this.pathLength;
						Point point;
						Point point2;
						pathGeometry.GetPointAtFractionLength(num2, out point, out point2);
						DrawingVisual drawingVisual = this.visualChildren[i] as DrawingVisual;
						TransformGroup transformGroup = drawingVisual.Transform as TransformGroup;
						ScaleTransform scaleTransform = transformGroup.Children[0] as ScaleTransform;
						RotateTransform rotateTransform = transformGroup.Children[1] as RotateTransform;
						TranslateTransform translateTransform = transformGroup.Children[2] as TranslateTransform;
						scaleTransform.ScaleX = num;
						scaleTransform.ScaleY = num;
						rotateTransform.Angle = Math.Atan2(point2.Y, point2.X) * 180.0 / 3.1415926535897931;
						rotateTransform.CenterX = num3 / 2.0;
						rotateTransform.CenterY = num4;
						translateTransform.X = point.X - num3 / 2.0;
						translateTransform.Y = point.Y - num4;
						Rect contentBounds = drawingVisual.ContentBounds;
						contentBounds.Transform(transformGroup.Value);
						this.boundingRect.Union(contentBounds);
						num2 += num3 / 2.0 / this.pathLength;
					}
					base.InvalidateMeasure();
				}
			}
		}
		private void WarpAllPoints(PathGeometry warpedTextPathGeometry, PathGeometry flattenedTextPathGeometry)
		{
			PathGeometry pathGeometry = new PathGeometry(new PathFigure[]
			{
				base.PathFigure
			});
			double scalingFactor = this.pathLength / this.textLength;
			this.LoopThroughAllFlattenedPathPoints(warpedTextPathGeometry, flattenedTextPathGeometry, delegate(Point pointSrc)
			{
				double progress = Math.Max(0.0, Math.Min(1.0, pointSrc.X / this.textLength));
				double num = scalingFactor * (this.baseline - pointSrc.Y);
				Point point;
				Point point2;
				pathGeometry.GetPointAtFractionLength(progress, out point, out point2);
				double num2 = Math.Atan2(point2.Y, point2.X);
				return new Point
				{
					X = point.X + num * Math.Sin(num2),
					Y = point.Y - num * Math.Cos(num2)
				};
			});
			if (this.ShiftToOrigin)
			{
				Rect boundsRect = warpedTextPathGeometry.Bounds;
				this.LoopThroughAllFlattenedPathPoints(warpedTextPathGeometry, warpedTextPathGeometry, (Point pointSrc) => new Point
				{
					X = pointSrc.X - boundsRect.Left,
					Y = pointSrc.Y - boundsRect.Top
				});
			}
		}
Example #17
0
    DrawBezierLabel
    (
        DrawingContext oDrawingContext,
        GraphDrawingContext oGraphDrawingContext,
        FormattedText oFormattedText,
        Point oEdgeEndpoint1,
        Point oEdgeEndpoint2,
        PathGeometry oBezierCurve,
        Double dLabelOriginAsFractionOfEdgeLength,
        Double dEdgeLength,
        Double dBufferWidth,
        Color oLabelTextColor,
        Color oTranslucentRectangleColor,
        Double dFontSize
    )
    {
        Debug.Assert(oDrawingContext != null);
        Debug.Assert(oGraphDrawingContext != null);
        Debug.Assert(oFormattedText != null);
        Debug.Assert(oBezierCurve != null);
        Debug.Assert(dLabelOriginAsFractionOfEdgeLength >= 0);
        Debug.Assert(dEdgeLength >= 0);
        Debug.Assert(dBufferWidth >= 0);
        Debug.Assert(dFontSize > 0);
        AssertValid();

        // This method uses a modified version of the technique described in
        // "Render Text On A Path With WPF," by Charles Petzold, at
        // http://msdn.microsoft.com/en-us/magazine/dd263097.aspx.

        if (oEdgeEndpoint2.X < oEdgeEndpoint1.X)
        {
            // Don't let text be drawn upside-down.

            WpfGraphicsUtil.SwapPoints(ref oEdgeEndpoint1, ref oEdgeEndpoint2);

            oBezierCurve = WpfPathGeometryUtil.ReverseQuadraticBezierCurve(
                oBezierCurve);
        }

        Double dTextWidth = oFormattedText.Width;
        Double dTextWidthToEdgeLengthRatio = dTextWidth / dEdgeLength;

        Double dLineOffset = 0;
        Point oOrigin = new Point(0, 0);

        String [] asLines =
            oFormattedText.Text.Split( new char[] {'\r', '\n'} );

        foreach (String sLine in asLines)
        {
            // The label characters will be drawn one by one using positions
            // computed by PathGeometry.GetPointAtFractionLength().  The first
            // character will be at dLabelOriginAsFractionOfEdgeLength.

            Double dFractionOfEdgeLength = dLabelOriginAsFractionOfEdgeLength;

            Boolean bUsedEllipses = false;

            foreach (Char c in sLine)
            {
                if (bUsedEllipses)
                {
                    break;
                }

                Point oPointAtFractionLength;
                Point oPointTangent;

                oBezierCurve.GetPointAtFractionLength(dFractionOfEdgeLength,
                    out oPointAtFractionLength, out oPointTangent);

                Double dCharacterAngleDegrees = MathUtil.RadiansToDegrees(
                    Math.Atan2(oPointTangent.Y, oPointTangent.X) );

                String sChar = c.ToString();

                if ( (oPointAtFractionLength - oEdgeEndpoint2).Length <=
                    6.0 * dBufferWidth)
                {
                    // There is probably not enough room for the rest of the
                    // string.  Terminate it with ellipses.  (The buffer width
                    // multiple was determined experimentally.)

                    bUsedEllipses = true;
                    sChar = "...";
                }

                FormattedText oCharacterFormattedText =
                    m_oFormattedTextManager.CreateFormattedText(
                        sChar, oLabelTextColor, dFontSize, m_dGraphScale);

                Double dCharacterWidth =
                    oCharacterFormattedText.WidthIncludingTrailingWhitespace;

                Double dCharacterHeight = oCharacterFormattedText.Height;

                // Apply a RotateTransform to make the character's base
                // approximately parallel to the Bezier curve's tangent, and a
                // TranslateTransform to vertically position the character.

                oDrawingContext.PushTransform( new TranslateTransform(
                    oPointAtFractionLength.X,

                    oPointAtFractionLength.Y - (oFormattedText.Height / 2.0)
                        + dLineOffset
                    ) );

                oDrawingContext.PushTransform( new RotateTransform(
                    dCharacterAngleDegrees, 0,
                    (oFormattedText.Height / 2.0) - dLineOffset
                    ) );

                // A translucent rectangle is drawn for each character.
                // Rounding errors cause the underlying edge to show through
                // faintly between the rectangles, which is a bug.  How to fix
                // this?

                Rect oTranslucentRectangle = new Rect( oOrigin,
                    new Size(dCharacterWidth, dCharacterHeight) );

                DrawTranslucentRectangle(oDrawingContext,
                    oTranslucentRectangle, oTranslucentRectangleColor);

                oDrawingContext.DrawText(oCharacterFormattedText, oOrigin);

                oDrawingContext.Pop();
                oDrawingContext.Pop();

                dFractionOfEdgeLength += dCharacterWidth / dEdgeLength;
            }

            dLineOffset += oFormattedText.Height / asLines.Length;
        }
    }
		protected override void OnRender(DrawingContext dc)
		{
			if (this.pathLength != 0.0 && this.textLength != 0.0)
			{
				double num = this.pathLength / this.textLength;
				num = 1.0;
				double num2 = 0.0;
				PathGeometry pathGeometry = new PathGeometry(new PathFigure[]
				{
					base.PathFigure
				});
				foreach (FormattedText current in this.formattedChars)
				{
					double num3 = num * current.WidthIncludingTrailingWhitespace;
					double num4 = num * current.Baseline;
					num2 += num3 / 2.0 / this.pathLength;
					Point point;
					Point point2;
					pathGeometry.GetPointAtFractionLength(num2, out point, out point2);
					dc.PushTransform(new TranslateTransform(point.X - num3 / 2.0, point.Y - num4));
					dc.PushTransform(new RotateTransform(Math.Atan2(point2.Y, point2.X) * 180.0 / 3.1415926535897931, num3 / 2.0, num4));
					dc.PushTransform(new ScaleTransform(num, num));
					dc.DrawText(current, new Point(0.0, 0.0));
					dc.Pop();
					dc.Pop();
					dc.Pop();
					num2 += num3 / 2.0 / this.pathLength;
				}
			}
		}