Пример #1
0
        /// <summary>
        /// Calculates the bounds with respect to rotation angle and horizontal/vertical alignment.
        /// </summary>
        /// <param name="bounds">The size of the object to calculate bounds for.</param>
        /// <param name="angle">The rotation angle (degrees).</param>
        /// <param name="horizontalAlignment">The horizontal alignment.</param>
        /// <param name="verticalAlignment">The vertical alignment.</param>
        /// <returns>A minimum bounding rectangle.</returns>
        public static OxyRect GetBounds(this OxySize bounds, double angle, HorizontalAlignment horizontalAlignment, VerticalAlignment verticalAlignment)
        {
            var u = horizontalAlignment == HorizontalAlignment.Left ? 0 : horizontalAlignment == HorizontalAlignment.Center ? 0.5 : 1;
            var v = verticalAlignment == VerticalAlignment.Top ? 0 : verticalAlignment == VerticalAlignment.Middle ? 0.5 : 1;

            var origin = new ScreenVector(u * bounds.Width, v * bounds.Height);

            if (angle == 0)
            {
                return(new OxyRect(-origin.X, -origin.Y, bounds.Width, bounds.Height));
            }

            // the corners of the rectangle
            var p0 = new ScreenVector(0, 0) - origin;
            var p1 = new ScreenVector(bounds.Width, 0) - origin;
            var p2 = new ScreenVector(bounds.Width, bounds.Height) - origin;
            var p3 = new ScreenVector(0, bounds.Height) - origin;

            var theta = angle * Math.PI / 180.0;
            var costh = Math.Cos(theta);
            var sinth = Math.Sin(theta);
            Func <ScreenVector, ScreenVector> rotate = p => new ScreenVector((costh * p.X) - (sinth * p.Y), (sinth * p.X) + (costh * p.Y));

            var q0 = rotate(p0);
            var q1 = rotate(p1);
            var q2 = rotate(p2);
            var q3 = rotate(p3);

            var x = Math.Min(Math.Min(q0.X, q1.X), Math.Min(q2.X, q3.X));
            var y = Math.Min(Math.Min(q0.Y, q1.Y), Math.Min(q2.Y, q3.Y));
            var w = Math.Max(Math.Max(q0.X - x, q1.X - x), Math.Max(q2.X - x, q3.X - x));
            var h = Math.Max(Math.Max(q0.Y - y, q1.Y - y), Math.Max(q2.Y - y, q3.Y - y));

            return(new OxyRect(x, y, w, h));
        }
Пример #2
0
        /// <summary>
        /// Gets the polygon outline of the specified rotated and aligned box.
        /// </summary>
        /// <param name="size">The size of the  box.</param>
        /// <param name="origin">The origin of the box.</param>
        /// <param name="angle">The rotation angle of the box.</param>
        /// <param name="horizontalAlignment">The horizontal alignment of the box.</param>
        /// <param name="verticalAlignment">The vertical alignment of the box.</param>
        /// <returns>A sequence of points defining the polygon outline of the box.</returns>
        public static IEnumerable <ScreenPoint> GetPolygon(this OxySize size, ScreenPoint origin, double angle, HorizontalAlignment horizontalAlignment, VerticalAlignment verticalAlignment)
        {
            var u = horizontalAlignment == HorizontalAlignment.Left ? 0 : horizontalAlignment == HorizontalAlignment.Center ? 0.5 : 1;
            var v = verticalAlignment == VerticalAlignment.Top ? 0 : verticalAlignment == VerticalAlignment.Middle ? 0.5 : 1;

            var offset = new ScreenVector(u * size.Width, v * size.Height);

            // the corners of the rectangle
            var p0 = new ScreenVector(0, 0) - offset;
            var p1 = new ScreenVector(size.Width, 0) - offset;
            var p2 = new ScreenVector(size.Width, size.Height) - offset;
            var p3 = new ScreenVector(0, size.Height) - offset;

            if (angle != 0)
            {
                var theta = angle * Math.PI / 180.0;
                var costh = Math.Cos(theta);
                var sinth = Math.Sin(theta);
                Func <ScreenVector, ScreenVector> rotate = p => new ScreenVector((costh * p.X) - (sinth * p.Y), (sinth * p.X) + (costh * p.Y));

                p0 = rotate(p0);
                p1 = rotate(p1);
                p2 = rotate(p2);
                p3 = rotate(p3);
            }

            yield return(origin + p0);

            yield return(origin + p1);

            yield return(origin + p2);

            yield return(origin + p3);
        }
        /// <summary>
        /// Calculates the maximum size of the specified axes.
        /// </summary>
        /// <param name="rc">
        /// The render context.
        /// </param>
        /// <param name="axesOfPositionTier">
        /// The axes of position tier.
        /// </param>
        /// <returns>
        /// The maximum size.
        /// </returns>
        private static double MaxSizeOfPositionTier(IRenderContext rc, IEnumerable <Axis> axesOfPositionTier)
        {
            double maxSizeOfPositionTier = 0;

            foreach (var axis in axesOfPositionTier)
            {
                OxySize size = axis.Measure(rc);
                if (axis.IsHorizontal())
                {
                    if (size.Height > maxSizeOfPositionTier)
                    {
                        maxSizeOfPositionTier = size.Height;
                    }
                }
                else
                {
                    if (size.Width > maxSizeOfPositionTier)
                    {
                        maxSizeOfPositionTier = size.Width;
                    }
                }
            }

            return(maxSizeOfPositionTier);
        }
Пример #4
0
        /// <summary>
        /// Draws or measures text containing sub- and superscript.
        /// </summary>
        /// <param name="rc">The render context.</param>
        /// <param name="pt">The point.</param>
        /// <param name="text">The text.</param>
        /// <param name="textColor">Color of the text.</param>
        /// <param name="fontFamily">The font family.</param>
        /// <param name="fontSize">The font size.</param>
        /// <param name="fontWeight">The font weight.</param>
        /// <param name="angle">The angle.</param>
        /// <param name="ha">The horizontal alignment.</param>
        /// <param name="va">The vertical alignment.</param>
        /// <param name="maxsize">The maximum size of the text.</param>
        /// <param name="measure">Measure the size of the text if set to <c>true</c>.</param>
        /// <returns>The size of the text.</returns>
        /// <example>Subscript: H_{2}O
        /// Superscript: E=mc^{2}
        /// Both: A^{2}_{i,j}</example>
        public static OxySize DrawMathText(
            this IRenderContext rc,
            ScreenPoint pt,
            string text,
            OxyColor textColor,
            string fontFamily,
            double fontSize,
            double fontWeight,
            double angle,
            HorizontalAlignment ha,
            VerticalAlignment va,
            OxySize? maxsize,
            bool measure)
        {
            if (string.IsNullOrEmpty(text))
            {
                return OxySize.Empty;
            }

            if (text.Contains("^{") || text.Contains("_{"))
            {
                double x = pt.X;
                double y = pt.Y;

                // Measure
                var size = InternalDrawMathText(rc, x, y, text, textColor, fontFamily, fontSize, fontWeight, true, angle);

                switch (ha)
                {
                    case HorizontalAlignment.Right:
                        x -= size.Width;
                        break;
                    case HorizontalAlignment.Center:
                        x -= size.Width * 0.5;
                        break;
                }

                switch (va)
                {
                    case VerticalAlignment.Bottom:
                        y -= size.Height;
                        break;
                    case VerticalAlignment.Middle:
                        y -= size.Height * 0.5;
                        break;
                }

                InternalDrawMathText(rc, x, y, text, textColor, fontFamily, fontSize, fontWeight, false, angle);
                return measure ? size : OxySize.Empty;
            }

            rc.DrawText(pt, text, textColor, fontFamily, fontSize, fontWeight, angle, ha, va, maxsize);
            if (measure)
            {
                return rc.MeasureText(text, fontFamily, fontSize, fontWeight);
            }

            return OxySize.Empty;
        }
        /// <summary>
        /// Gets the coordinates of the (rotated) background rectangle.
        /// </summary>
        /// <param name="position">
        /// The position.
        /// </param>
        /// <param name="size">
        /// The size.
        /// </param>
        /// <param name="padding">
        /// The padding.
        /// </param>
        /// <param name="rotation">
        /// The rotation.
        /// </param>
        /// <param name="horizontalAlignment">
        /// The horizontal alignment.
        /// </param>
        /// <param name="verticalAlignment">
        /// The vertical alignment.
        /// </param>
        /// <returns>
        /// The background rectangle coordinates.
        /// </returns>
        private static IList <ScreenPoint> GetTextBounds(
            ScreenPoint position,
            OxySize size,
            OxyThickness padding,
            double rotation,
            HorizontalTextAlign horizontalAlignment,
            VerticalTextAlign verticalAlignment)
        {
            double left, right, top, bottom;

            switch (horizontalAlignment)
            {
            case HorizontalTextAlign.Center:
                left  = -size.Width * 0.5;
                right = -left;
                break;

            case HorizontalTextAlign.Right:
                left  = -size.Width;
                right = 0;
                break;

            default:
                left  = 0;
                right = size.Width;
                break;
            }

            switch (verticalAlignment)
            {
            case VerticalTextAlign.Middle:
                top    = -size.Height * 0.5;
                bottom = -top;
                break;

            case VerticalTextAlign.Bottom:
                top    = -size.Height;
                bottom = 0;
                break;

            default:
                top    = 0;
                bottom = size.Height;
                break;
            }

            double cost    = Math.Cos(rotation / 180 * Math.PI);
            double sint    = Math.Sin(rotation / 180 * Math.PI);
            var    u       = new ScreenVector(cost, sint);
            var    v       = new ScreenVector(-sint, cost);
            var    polygon = new ScreenPoint[4];

            polygon[0] = position + u * (left - padding.Left) + v * (top - padding.Top);
            polygon[1] = position + u * (right + padding.Right) + v * (top - padding.Top);
            polygon[2] = position + u * (right + padding.Right) + v * (bottom + padding.Bottom);
            polygon[3] = position + u * (left - padding.Left) + v * (bottom + padding.Bottom);
            return(polygon);
        }
        /// <summary>
        /// Measures the size of the title and subtitle.
        /// </summary>
        /// <param name="rc">
        /// The rendering context.
        /// </param>
        /// <returns>
        /// Size of the titles.
        /// </returns>
        private OxySize MeasureTitles(IRenderContext rc)
        {
            OxySize size1 = rc.MeasureText(this.Title, this.ActualTitleFont, this.TitleFontSize, this.TitleFontWeight);
            OxySize size2 = rc.MeasureText(
                this.Subtitle, this.SubtitleFont ?? this.ActualSubtitleFont, this.SubtitleFontSize, this.SubtitleFontWeight);
            double height = size1.Height + size2.Height;
            double width  = Math.Max(size1.Width, size2.Width);

            return(new OxySize(width, height));
        }
Пример #7
0
        public OxySize MeasureText(string text, string fontFamily = "",
		                    double fontSize = 10, double fontWeight = 500)
        {
            FontDescription desc = new FontDescription();
            OxySize size = new OxySize();
            int width, height;

            desc.Family = fontFamily;
            desc.Size = Pango.Units.FromPixels ((int) fontSize);
            desc.Weight = PangoWeightFromDouble (fontWeight);
            layout.FontDescription = desc;
            layout.SetMarkup (GLib.Markup.EscapeText (text));
            layout.GetPixelSize (out width, out height);
            size.Width = (double) width;
            size.Height = (double) height;
            return size;
        }
        /// <summary>
        /// Renders the title and subtitle.
        /// </summary>
        /// <param name="rc">
        /// The render context.
        /// </param>
        private void RenderTitle(IRenderContext rc)
        {
            OxySize size1 = rc.MeasureText(this.Title, this.ActualTitleFont, this.TitleFontSize, this.TitleFontWeight);

            rc.MeasureText(
                this.Subtitle, this.SubtitleFont ?? this.ActualSubtitleFont, this.SubtitleFontSize, this.SubtitleFontWeight);

            // double height = size1.Height + size2.Height;
            // double dy = (TitleArea.Top+TitleArea.Bottom-height)*0.5;
            double dy = this.TitleArea.Top;
            double dx = (this.TitleArea.Left + this.TitleArea.Right) * 0.5;

            if (!string.IsNullOrEmpty(this.Title))
            {
                rc.DrawMathText(
                    new ScreenPoint(dx, dy),
                    this.Title,
                    this.TitleColor ?? this.TextColor,
                    this.ActualTitleFont,
                    this.TitleFontSize,
                    this.TitleFontWeight,
                    0,
                    HorizontalAlignment.Center,
                    VerticalAlignment.Top);
                dy += size1.Height;
            }

            if (!string.IsNullOrEmpty(this.Subtitle))
            {
                rc.DrawMathText(
                    new ScreenPoint(dx, dy),
                    this.Subtitle,
                    this.SubtitleColor ?? this.TextColor,
                    this.ActualSubtitleFont,
                    this.SubtitleFontSize,
                    this.SubtitleFontWeight,
                    0,
                    HorizontalAlignment.Center,
                    VerticalAlignment.Top);
            }
        }
        /// <summary>
        /// The measure string.
        /// </summary>
        /// <param name="faceName">
        /// The font face name.
        /// </param>
        /// <param name="height">
        /// The height.
        /// </param>
        /// <param name="weight">
        /// The weight.
        /// </param>
        /// <param name="str">
        /// The string.
        /// </param>
        /// <returns>
        /// The size of the rendered string.
        /// </returns>
        public static OxySize MeasureString(string faceName, int height, int weight, string str)
        {
            var     lines  = Regex.Split(str, "\r\n");
            OxySize result = new OxySize(0, 0);

            foreach (var line in lines)
            {
                var hfont  = CreateFont(height, 0, 0, 0, weight, 0, 0, 0, 0, 0, 0, 0, 0, faceName);
                var hdc    = GetDC(IntPtr.Zero);
                var oldobj = SelectObject(hdc, hfont);
                var temp   = GetTextExtent(hdc, line);
                SelectObject(hdc, oldobj);
                DeleteObject(hfont);
                DeleteDC(hdc);
                var lineSpacing = temp.Height / 3.0;
                result.Height += temp.Height + lineSpacing;
                result.Width   = Math.Max(temp.Width * 1.28, result.Width);
            }

            return(result);
        }
        public void RenderTitle(string title, string subtitle)
        {
            OxySize size1  = rc.MeasureText(title, plot.TitleFont, plot.TitleFontSize, plot.TitleFontWeight);
            OxySize size2  = rc.MeasureText(subtitle, plot.TitleFont, plot.TitleFontSize, plot.TitleFontWeight);
            double  height = size1.Height + size2.Height;
            double  dy     = (plot.AxisMargins.Top - height) * 0.5;
            double  dx     = (plot.Bounds.Left + plot.Bounds.Right) * 0.5;

            if (!String.IsNullOrEmpty(title))
            {
                rc.DrawText(
                    new ScreenPoint(dx, dy), title, plot.TextColor,
                    plot.TitleFont, plot.TitleFontSize, plot.TitleFontWeight,
                    0,
                    HorizontalTextAlign.Center, VerticalTextAlign.Top);
            }
            if (!String.IsNullOrEmpty(subtitle))
            {
                rc.DrawText(new ScreenPoint(dx, dy + size1.Height), subtitle, plot.TextColor,
                            plot.TitleFont, plot.SubtitleFontSize, plot.SubtitleFontWeight, 0,
                            HorizontalTextAlign.Center, VerticalTextAlign.Top);
            }
        }
        /// <summary>
        /// Renders the axis title.
        /// </summary>
        /// <param name="axis">
        /// The axis.
        /// </param>
        /// <param name="titlePosition">
        /// The title position.
        /// </param>
        private void RenderAxisTitle(Axis axis, double titlePosition)
        {
            bool isHorizontal = axis.IsHorizontal();

            OxySize?maxSize = null;

            if (axis.ClipTitle)
            {
                // Calculate the title clipping dimensions
                double screenLength = isHorizontal
                                          ? Math.Abs(axis.ScreenMax.X - axis.ScreenMin.X)
                                          : Math.Abs(axis.ScreenMax.Y - axis.ScreenMin.Y);

                maxSize = new OxySize(screenLength * axis.TitleClippingLength, double.MaxValue);
            }

            double angle = -90;

            var halign = HorizontalAlignment.Center;
            var valign = VerticalAlignment.Top;

            var lpt = this.GetAxisTitlePositionAndAlignment(axis, titlePosition, ref angle, ref halign, ref valign);

            this.rc.SetToolTip(axis.ToolTip);
            this.rc.DrawMathText(
                lpt,
                axis.ActualTitle,
                axis.ActualTitleColor,
                axis.ActualTitleFont,
                axis.ActualTitleFontSize,
                axis.ActualTitleFontWeight,
                angle,
                halign,
                valign,
                maxSize);
            this.rc.SetToolTip(null);
        }
Пример #12
0
 /// <summary>
 /// Draws text.
 /// </summary>
 /// <param name="p">The position.</param>
 /// <param name="text">The text.</param>
 /// <param name="fill">The text color.</param>
 /// <param name="fontFamily">The font family.</param>
 /// <param name="fontSize">Size of the font (in device independent units, 1/96 inch).</param>
 /// <param name="fontWeight">The font weight.</param>
 /// <param name="rotate">The rotation angle.</param>
 /// <param name="halign">The horizontal alignment.</param>
 /// <param name="valign">The vertical alignment.</param>
 /// <param name="maxSize">The maximum size of the text (in device independent units, 1/96 inch).</param>
 public void DrawText(
     ScreenPoint p,
     string text,
     OxyColor fill,
     string fontFamily = null,
     double fontSize = 10,
     double fontWeight = 500,
     double rotate = 0,
     HorizontalAlignment halign = HorizontalAlignment.Left,
     VerticalAlignment valign = VerticalAlignment.Top,
     OxySize? maxSize = null)
 {
 }
Пример #13
0
        /// <summary>
        /// Gets the rectangle of the legend box.
        /// </summary>
        /// <param name="legendSize">Size of the legend box.</param>
        /// <returns>A rectangle.</returns>
        private OxyRect GetLegendRectangle(OxySize legendSize)
        {
            double top = 0;
            double left = 0;
            if (this.LegendPlacement == LegendPlacement.Outside)
            {
                switch (this.LegendPosition)
                {
                    case LegendPosition.LeftTop:
                    case LegendPosition.LeftMiddle:
                    case LegendPosition.LeftBottom:
                        left = this.PlotAndAxisArea.Left - legendSize.Width - this.LegendMargin;
                        break;
                    case LegendPosition.RightTop:
                    case LegendPosition.RightMiddle:
                    case LegendPosition.RightBottom:
                        left = this.PlotAndAxisArea.Right + this.LegendMargin;
                        break;
                    case LegendPosition.TopLeft:
                    case LegendPosition.TopCenter:
                    case LegendPosition.TopRight:
                        top = this.PlotAndAxisArea.Top - legendSize.Height - this.LegendMargin;
                        break;
                    case LegendPosition.BottomLeft:
                    case LegendPosition.BottomCenter:
                    case LegendPosition.BottomRight:
                        top = this.PlotAndAxisArea.Bottom + this.LegendMargin;
                        break;
                }

                switch (this.LegendPosition)
                {
                    case LegendPosition.TopLeft:
                    case LegendPosition.BottomLeft:
                        left = this.PlotArea.Left;
                        break;
                    case LegendPosition.TopRight:
                    case LegendPosition.BottomRight:
                        left = this.PlotArea.Right - legendSize.Width;
                        break;
                    case LegendPosition.LeftTop:
                    case LegendPosition.RightTop:
                        top = this.PlotArea.Top;
                        break;
                    case LegendPosition.LeftBottom:
                    case LegendPosition.RightBottom:
                        top = this.PlotArea.Bottom - legendSize.Height;
                        break;
                    case LegendPosition.LeftMiddle:
                    case LegendPosition.RightMiddle:
                        top = (this.PlotArea.Top + this.PlotArea.Bottom - legendSize.Height) * 0.5;
                        break;
                    case LegendPosition.TopCenter:
                    case LegendPosition.BottomCenter:
                        left = (this.PlotArea.Left + this.PlotArea.Right - legendSize.Width) * 0.5;
                        break;
                }
            }
            else
            {
                switch (this.LegendPosition)
                {
                    case LegendPosition.LeftTop:
                    case LegendPosition.LeftMiddle:
                    case LegendPosition.LeftBottom:
                        left = this.PlotArea.Left + this.LegendMargin;
                        break;
                    case LegendPosition.RightTop:
                    case LegendPosition.RightMiddle:
                    case LegendPosition.RightBottom:
                        left = this.PlotArea.Right - legendSize.Width - this.LegendMargin;
                        break;
                    case LegendPosition.TopLeft:
                    case LegendPosition.TopCenter:
                    case LegendPosition.TopRight:
                        top = this.PlotArea.Top + this.LegendMargin;
                        break;
                    case LegendPosition.BottomLeft:
                    case LegendPosition.BottomCenter:
                    case LegendPosition.BottomRight:
                        top = this.PlotArea.Bottom - legendSize.Height - this.LegendMargin;
                        break;
                }

                switch (this.LegendPosition)
                {
                    case LegendPosition.TopLeft:
                    case LegendPosition.BottomLeft:
                        left = this.PlotArea.Left + this.LegendMargin;
                        break;
                    case LegendPosition.TopRight:
                    case LegendPosition.BottomRight:
                        left = this.PlotArea.Right - legendSize.Width - this.LegendMargin;
                        break;
                    case LegendPosition.LeftTop:
                    case LegendPosition.RightTop:
                        top = this.PlotArea.Top + this.LegendMargin;
                        break;
                    case LegendPosition.LeftBottom:
                    case LegendPosition.RightBottom:
                        top = this.PlotArea.Bottom - legendSize.Height - this.LegendMargin;
                        break;

                    case LegendPosition.LeftMiddle:
                    case LegendPosition.RightMiddle:
                        top = (this.PlotArea.Top + this.PlotArea.Bottom - legendSize.Height) * 0.5;
                        break;
                    case LegendPosition.TopCenter:
                    case LegendPosition.BottomCenter:
                        left = (this.PlotArea.Left + this.PlotArea.Right - legendSize.Width) * 0.5;
                        break;
                }
            }

            return new OxyRect(left, top, legendSize.Width, legendSize.Height);
        }
Пример #14
0
        /// <summary>
        /// Renders the legend for the specified series.
        /// </summary>
        /// <param name="rc">The render context.</param>
        /// <param name="s">The series.</param>
        /// <param name="rect">The position and size of the legend.</param>
        private void RenderLegend(IRenderContext rc, Series.Series s, OxyRect rect)
        {
            var actualItemAlignment = this.LegendItemAlignment;
            if (this.LegendOrientation == LegendOrientation.Horizontal)
            {
                // center/right alignment is not supported for horizontal orientation
                actualItemAlignment = HorizontalAlignment.Left;
            }

            double x = rect.Left;
            switch (actualItemAlignment)
            {
                case HorizontalAlignment.Center:
                    x = (rect.Left + rect.Right) / 2;
                    if (this.LegendSymbolPlacement == LegendSymbolPlacement.Left)
                    {
                        x -= (this.LegendSymbolLength + this.LegendSymbolMargin) / 2;
                    }
                    else
                    {
                        x -= (this.LegendSymbolLength + this.LegendSymbolMargin) / 2;
                    }

                    break;
                case HorizontalAlignment.Right:
                    x = rect.Right;

                    // if (LegendSymbolPlacement == LegendSymbolPlacement.Right)
                    x -= this.LegendSymbolLength + this.LegendSymbolMargin;
                    break;
            }

            if (this.LegendSymbolPlacement == LegendSymbolPlacement.Left)
            {
                x += this.LegendSymbolLength + this.LegendSymbolMargin;
            }

            double y = rect.Top;
            var maxsize = new OxySize(Math.Max(rect.Width - this.LegendSymbolLength - this.LegendSymbolMargin, 0), rect.Height);

            rc.SetToolTip(s.ToolTip);
            var textSize = rc.DrawMathText(
                new ScreenPoint(x, y),
                s.Title,
                this.LegendTextColor.GetActualColor(this.TextColor),
                this.LegendFont ?? this.DefaultFont,
                this.LegendFontSize,
                this.LegendFontWeight,
                0,
                actualItemAlignment,
                VerticalAlignment.Top,
                maxsize,
                true);
            double x0 = x;
            switch (actualItemAlignment)
            {
                case HorizontalAlignment.Center:
                    x0 = x - (textSize.Width * 0.5);
                    break;
                case HorizontalAlignment.Right:
                    x0 = x - textSize.Width;
                    break;
            }

            var symbolRect =
                new OxyRect(
                    this.LegendSymbolPlacement == LegendSymbolPlacement.Right
                        ? x0 + textSize.Width + this.LegendSymbolMargin
                        : x0 - this.LegendSymbolMargin - this.LegendSymbolLength,
                    rect.Top,
                    this.LegendSymbolLength,
                    textSize.Height);

            s.RenderLegend(rc, symbolRect);
            rc.SetToolTip(null);
        }
        /// <summary>
        /// Calculates the bounds with respect to rotation angle and horizontal/vertical alignment.
        /// </summary>
        /// <param name="bounds">The size of the object to calculate bounds for.</param>
        /// <param name="angle">The rotation angle (degrees).</param>
        /// <returns>A minimum bounding rectangle.</returns>
        private static OxySize MeasureRotatedRectangleBound(OxySize bounds, double angle)
        {
            var oxyRect = bounds.GetBounds(angle, HorizontalAlignment.Center, VerticalAlignment.Middle);

            return(new OxySize(oxyRect.Width, oxyRect.Height));
        }
        /// <summary>
        /// Renders the axis title.
        /// </summary>
        /// <param name="axis">
        /// The axis.
        /// </param>
        /// <param name="titlePosition">
        /// The title position.
        /// </param>
        private void RenderAxisTitle(Axis axis, double titlePosition)
        {
            bool isHorizontal = axis.IsHorizontal();

            OxySize? maxSize = null;

            if (axis.ClipTitle)
            {
                // Calculate the title clipping dimensions
                double screenLength = isHorizontal
                                          ? Math.Abs(axis.ScreenMax.X - axis.ScreenMin.X)
                                          : Math.Abs(axis.ScreenMax.Y - axis.ScreenMin.Y);

                maxSize = new OxySize(screenLength * axis.TitleClippingLength, double.MaxValue);
            }

            double angle = -90;

            var halign = HorizontalTextAlign.Center;
            var valign = VerticalTextAlign.Top;

            var lpt = this.GetAxisTitlePositionAndAlignment(axis, titlePosition, ref angle, ref halign, ref valign);

            this.rc.SetToolTip(axis.ToolTip);
            this.rc.DrawText(
                lpt, 
                axis.ActualTitle, 
                axis.ActualTitleColor, 
                axis.ActualTitleFont, 
                axis.ActualTitleFontSize, 
                axis.ActualTitleFontWeight, 
                angle, 
                halign, 
                valign, 
                maxSize);
            this.rc.SetToolTip(null);
        }
 /// <summary>
 /// Draws the clipped text.
 /// </summary>
 /// <param name="rc">The rendering context.</param>
 /// <param name="clippingRectangle">The clipping rectangle.</param>
 /// <param name="p">The position.</param>
 /// <param name="text">The text.</param>
 /// <param name="fill">The fill color.</param>
 /// <param name="fontFamily">The font family.</param>
 /// <param name="fontSize">Size of the font.</param>
 /// <param name="fontWeight">The font weight.</param>
 /// <param name="rotate">The rotation angle.</param>
 /// <param name="horizontalAlignment">The horizontal align.</param>
 /// <param name="verticalAlignment">The vertical align.</param>
 /// <param name="maxSize">Size of the max.</param>
 public static void DrawClippedText(
     this IRenderContext rc,
     OxyRect clippingRectangle,
     ScreenPoint p,
     string text,
     OxyColor fill,
     string fontFamily = null,
     double fontSize = 10,
     double fontWeight = 500,
     double rotate = 0,
     HorizontalTextAlign horizontalAlignment = HorizontalTextAlign.Left,
     VerticalTextAlign verticalAlignment = VerticalTextAlign.Top,
     OxySize? maxSize = null)
 {
     if (clippingRectangle.Contains(p.X, p.Y))
     {
         rc.DrawText(p, text, fill, fontFamily, fontSize, fontWeight, rotate, horizontalAlignment, verticalAlignment, maxSize);
     }
 }
Пример #18
0
        /// <summary>
        /// Renders the legend for the specified series.
        /// </summary>
        /// <param name="rc">
        /// The render context.
        /// </param>
        /// <param name="s">
        /// The series.
        /// </param>
        /// <param name="rect">
        /// The position and size of the legend.
        /// </param>
        private void RenderLegend(IRenderContext rc, Series.Series s, OxyRect rect)
        {
            double x = rect.Left;
            switch (this.LegendItemAlignment)
            {
                case HorizontalAlignment.Center:
                    x = (rect.Left + rect.Right) / 2;
                    if (this.LegendSymbolPlacement == LegendSymbolPlacement.Left)
                    {
                        x -= (this.LegendSymbolLength + this.LegendSymbolMargin) / 2;
                    }
                    else
                    {
                        x -= (this.LegendSymbolLength + this.LegendSymbolMargin) / 2;
                    }

                    break;
                case HorizontalAlignment.Right:
                    x = rect.Right;

                    // if (LegendSymbolPlacement == LegendSymbolPlacement.Right)
                    x -= this.LegendSymbolLength + this.LegendSymbolMargin;
                    break;
            }

            if (this.LegendSymbolPlacement == LegendSymbolPlacement.Left)
            {
                x += this.LegendSymbolLength + this.LegendSymbolMargin;
            }

            double y = rect.Top;
            var maxsize = new OxySize(Math.Max(rect.Right - x, 0), Math.Max(rect.Bottom - y, 0));

            var textSize = rc.DrawMathText(
                new ScreenPoint(x, y),
                s.Title,
                this.LegendTextColor ?? this.TextColor,
                this.LegendFont ?? this.DefaultFont,
                this.LegendFontSize,
                this.LegendFontWeight,
                0,
                this.LegendItemAlignment,
                VerticalAlignment.Top,
                maxsize,
                true);
            double x0 = x;
            switch (this.LegendItemAlignment)
            {
                case HorizontalAlignment.Center:
                    x0 = x - (textSize.Width * 0.5);
                    break;
                case HorizontalAlignment.Right:
                    x0 = x - textSize.Width;
                    break;
            }

            var symbolRect =
                new OxyRect(
                    this.LegendSymbolPlacement == LegendSymbolPlacement.Right
                        ? x0 + textSize.Width + this.LegendSymbolMargin
                        : x0 - this.LegendSymbolMargin - this.LegendSymbolLength,
                    rect.Top,
                    this.LegendSymbolLength,
                    textSize.Height);

            s.RenderLegend(rc, symbolRect);
        }
        /// <summary>
        /// Draws the clipped text.
        /// </summary>
        /// <param name="rc">The rendering context.</param>
        /// <param name="clippingRectangle">The clipping rectangle.</param>
        /// <param name="p">The position.</param>
        /// <param name="text">The text.</param>
        /// <param name="fill">The fill color.</param>
        /// <param name="fontFamily">The font family.</param>
        /// <param name="fontSize">Size of the font.</param>
        /// <param name="fontWeight">The font weight.</param>
        /// <param name="rotate">The rotation angle.</param>
        /// <param name="horizontalAlignment">The horizontal align.</param>
        /// <param name="verticalAlignment">The vertical align.</param>
        /// <param name="maxSize">Size of the max.</param>
        public static void DrawClippedText(
            this IRenderContext rc,
            OxyRect clippingRectangle,
            ScreenPoint p,
            string text,
            OxyColor fill,
            string fontFamily = null,
            double fontSize = 10,
            double fontWeight = 500,
            double rotate = 0,
            HorizontalAlignment horizontalAlignment = HorizontalAlignment.Left,
            VerticalAlignment verticalAlignment = VerticalAlignment.Top,
            OxySize? maxSize = null)
        {
            if (rc.SetClip(clippingRectangle))
            {
                rc.DrawText(p, text, fill, fontFamily, fontSize, fontWeight, rotate, horizontalAlignment, verticalAlignment, maxSize);
                rc.ResetClip();
                return;
            }

            // fall back simply check position
            if (clippingRectangle.Contains(p.X, p.Y))
            {
                rc.DrawText(p, text, fill, fontFamily, fontSize, fontWeight, rotate, horizontalAlignment, verticalAlignment, maxSize);
            }
        }
Пример #20
0
 /// <summary>
 /// Initializes a new instance of the <see cref="OxyRect"/> struct by location and size.
 /// </summary>
 /// <param name="p0">The location.</param>
 /// <param name="size">The size.</param>
 public OxyRect(ScreenPoint p0, OxySize size)
     : this(p0.X, p0.Y, size.Width, size.Height)
 {
 }
Пример #21
0
 /// <summary>
 /// Calculates the bounds with respect to rotation angle and horizontal/vertical alignment.
 /// </summary>
 /// <param name="bounds">The size of the object to calculate bounds for.</param>
 /// <param name="angle">The rotation angle (degrees).</param>
 /// <returns>A minimum bounding rectangle.</returns>
 private static OxySize MeasureRotatedRectangleBound(OxySize bounds, double angle)
 {
     var oxyRect = bounds.GetBounds(angle, HorizontalAlignment.Center, VerticalAlignment.Middle);
     return new OxySize(oxyRect.Width, oxyRect.Height);
 }
Пример #22
0
 /// <summary>
 /// Draws the text.
 /// </summary>
 /// <param name="p">The position of the text.</param>
 /// <param name="text">The text.</param>
 /// <param name="fill">The fill color.</param>
 /// <param name="fontFamily">The font family.</param>
 /// <param name="fontSize">Size of the font.</param>
 /// <param name="fontWeight">The font weight.</param>
 /// <param name="rotate">The rotation angle.</param>
 /// <param name="halign">The horizontal alignment.</param>
 /// <param name="valign">The vertical alignment.</param>
 /// <param name="maxSize">The maximum size of the text.</param>
 public override void DrawText(
     ScreenPoint p,
     string text,
     OxyColor fill,
     string fontFamily,
     double fontSize,
     double fontWeight,
     double rotate,
     HorizontalAlignment halign,
     VerticalAlignment valign,
     OxySize? maxSize)
 {
     this.rc.DrawText(p, text, fill, this.GetFontFamily(fontFamily), fontSize, fontWeight, rotate, halign, valign, maxSize);
 }
Пример #23
0
        /// <summary>
        /// Renders the legend for the specified series.
        /// </summary>
        /// <param name="rc">
        /// The render context.
        /// </param>
        /// <param name="s">
        /// The series.
        /// </param>
        /// <param name="rect">
        /// The position and size of the legend.
        /// </param>
        private void RenderLegend(IRenderContext rc, Series s, OxyRect rect)
        {
            double x = rect.Left;

            switch (this.LegendItemAlignment)
            {
            case HorizontalTextAlign.Center:
                x = (rect.Left + rect.Right) / 2;
                if (this.LegendSymbolPlacement == LegendSymbolPlacement.Left)
                {
                    x -= (this.LegendSymbolLength + this.LegendSymbolMargin) / 2;
                }
                else
                {
                    x -= (this.LegendSymbolLength + this.LegendSymbolMargin) / 2;
                }

                break;

            case HorizontalTextAlign.Right:
                x = rect.Right;

                // if (LegendSymbolPlacement == LegendSymbolPlacement.Right)
                x -= this.LegendSymbolLength + this.LegendSymbolMargin;
                break;
            }

            if (this.LegendSymbolPlacement == LegendSymbolPlacement.Left)
            {
                x += this.LegendSymbolLength + this.LegendSymbolMargin;
            }

            double y       = rect.Top;
            var    maxsize = new OxySize(Math.Max(rect.Right - x, 0), Math.Max(rect.Bottom - y, 0));

            var textSize = rc.DrawMathText(
                new ScreenPoint(x, y),
                s.Title,
                this.LegendTextColor ?? this.TextColor,
                this.LegendFont ?? this.DefaultFont,
                this.LegendFontSize,
                this.LegendFontWeight,
                0,
                this.LegendItemAlignment,
                VerticalTextAlign.Top,
                maxsize,
                true);
            double x0 = x;

            switch (this.LegendItemAlignment)
            {
            case HorizontalTextAlign.Center:
                x0 = x - (textSize.Width * 0.5);
                break;

            case HorizontalTextAlign.Right:
                x0 = x - textSize.Width;
                break;
            }

            var symbolRect =
                new OxyRect(
                    this.LegendSymbolPlacement == LegendSymbolPlacement.Right
                        ? x0 + textSize.Width + this.LegendSymbolMargin
                        : x0 - this.LegendSymbolMargin - this.LegendSymbolLength,
                    rect.Top,
                    this.LegendSymbolLength,
                    textSize.Height);

            s.RenderLegend(rc, symbolRect);
        }
        /// <summary>
        /// The draw text.
        /// </summary>
        /// <param name="p">
        /// The p.
        /// </param>
        /// <param name="text">
        /// The text.
        /// </param>
        /// <param name="fill">
        /// The fill.
        /// </param>
        /// <param name="fontFamily">
        /// The font family.
        /// </param>
        /// <param name="fontSize">
        /// The font size.
        /// </param>
        /// <param name="fontWeight">
        /// The font weight.
        /// </param>
        /// <param name="rotate">
        /// The rotate.
        /// </param>
        /// <param name="halign">
        /// The halign.
        /// </param>
        /// <param name="valign">
        /// The valign.
        /// </param>
        /// <param name="maxSize">
        /// The maximum size of the text.
        /// </param>
        public override void DrawText(
            ScreenPoint p,
            string text,
            OxyColor fill,
            string fontFamily,
            double fontSize,
            double fontWeight,
            double rotate,
            HorizontalTextAlign halign,
            VerticalTextAlign valign,
            OxySize? maxSize)
        {
            FontStyle fs = FontStyle.Regular;
            if (fontWeight >= 700)
            {
                fs = FontStyle.Bold;
            }

            var font = new Font(fontFamily, (float)fontSize * FontsizeFactor, fs);

            var sf = new StringFormat { Alignment = StringAlignment.Near };

            SizeF size = this.g.MeasureString(text, font);
            if (maxSize != null)
            {
                if (size.Width > maxSize.Value.Width)
                {
                    size.Width = (float)maxSize.Value.Width;
                }

                if (size.Height > maxSize.Value.Height)
                {
                    size.Height = (float)maxSize.Value.Height;
                }
            }

            float dx = 0;
            if (halign == HorizontalTextAlign.Center)
            {
                dx = -size.Width / 2;

                // sf.Alignment = StringAlignment.Center;
            }

            if (halign == HorizontalTextAlign.Right)
            {
                dx = -size.Width;

                // sf.Alignment = StringAlignment.Far;
            }

            float dy = 0;
            sf.LineAlignment = StringAlignment.Near;
            if (valign == VerticalTextAlign.Middle)
            {
                // sf.LineAlignment = StringAlignment.Center;
                dy = -size.Height / 2;
            }

            if (valign == VerticalTextAlign.Bottom)
            {
                // sf.LineAlignment = StringAlignment.Far;
                dy = -size.Height;
            }

            this.g.TranslateTransform((float)p.X, (float)p.Y);
            if (Math.Abs(rotate) > double.Epsilon)
            {
                this.g.RotateTransform((float)rotate);
            }

            this.g.TranslateTransform(dx, dy);

            var layoutRectangle = new RectangleF(0, 0, size.Width, size.Height);
            this.g.DrawString(text, font, this.ToBrush(fill), layoutRectangle, sf);

            this.g.ResetTransform();
        }
Пример #25
0
 /// <summary>
 /// Measures the legends.
 /// </summary>
 /// <param name="rc">The render context.</param>
 /// <param name="availableSize">The available size for the legend box.</param>
 /// <returns>The size of the legend box.</returns>
 private OxySize MeasureLegends(IRenderContext rc, OxySize availableSize)
 {
     return(this.RenderOrMeasureLegends(rc, new OxyRect(0, 0, availableSize.Width, availableSize.Height), true));
 }
Пример #26
0
        /// <summary>
        /// Gets the rectangle of the legend box.
        /// </summary>
        /// <param name="legendSize">Size of the legend box.</param>
        /// <returns>A rectangle.</returns>
        private OxyRect GetLegendRectangle(OxySize legendSize)
        {
            double top  = 0;
            double left = 0;

            if (this.LegendPlacement == LegendPlacement.Outside)
            {
                switch (this.LegendPosition)
                {
                case LegendPosition.LeftTop:
                case LegendPosition.LeftMiddle:
                case LegendPosition.LeftBottom:
                    left = this.PlotAndAxisArea.Left - legendSize.Width - this.LegendMargin;
                    break;

                case LegendPosition.RightTop:
                case LegendPosition.RightMiddle:
                case LegendPosition.RightBottom:
                    left = this.PlotAndAxisArea.Right + this.LegendMargin;
                    break;

                case LegendPosition.TopLeft:
                case LegendPosition.TopCenter:
                case LegendPosition.TopRight:
                    top = this.PlotAndAxisArea.Top - legendSize.Height - this.LegendMargin;
                    break;

                case LegendPosition.BottomLeft:
                case LegendPosition.BottomCenter:
                case LegendPosition.BottomRight:
                    top = this.PlotAndAxisArea.Bottom + this.LegendMargin;
                    break;
                }

                switch (this.LegendPosition)
                {
                case LegendPosition.TopLeft:
                case LegendPosition.BottomLeft:
                    left = this.PlotArea.Left;
                    break;

                case LegendPosition.TopRight:
                case LegendPosition.BottomRight:
                    left = this.PlotArea.Right - legendSize.Width;
                    break;

                case LegendPosition.LeftTop:
                case LegendPosition.RightTop:
                    top = this.PlotArea.Top;
                    break;

                case LegendPosition.LeftBottom:
                case LegendPosition.RightBottom:
                    top = this.PlotArea.Bottom - legendSize.Height;
                    break;

                case LegendPosition.LeftMiddle:
                case LegendPosition.RightMiddle:
                    top = (this.PlotArea.Top + this.PlotArea.Bottom - legendSize.Height) * 0.5;
                    break;

                case LegendPosition.TopCenter:
                case LegendPosition.BottomCenter:
                    left = (this.PlotArea.Left + this.PlotArea.Right - legendSize.Width) * 0.5;
                    break;
                }
            }
            else
            {
                switch (this.LegendPosition)
                {
                case LegendPosition.LeftTop:
                case LegendPosition.LeftMiddle:
                case LegendPosition.LeftBottom:
                    left = this.PlotArea.Left + this.LegendMargin;
                    break;

                case LegendPosition.RightTop:
                case LegendPosition.RightMiddle:
                case LegendPosition.RightBottom:
                    left = this.PlotArea.Right - legendSize.Width - this.LegendMargin;
                    break;

                case LegendPosition.TopLeft:
                case LegendPosition.TopCenter:
                case LegendPosition.TopRight:
                    top = this.PlotArea.Top + this.LegendMargin;
                    break;

                case LegendPosition.BottomLeft:
                case LegendPosition.BottomCenter:
                case LegendPosition.BottomRight:
                    top = this.PlotArea.Bottom - legendSize.Height - this.LegendMargin;
                    break;
                }

                switch (this.LegendPosition)
                {
                case LegendPosition.TopLeft:
                case LegendPosition.BottomLeft:
                    left = this.PlotArea.Left + this.LegendMargin;
                    break;

                case LegendPosition.TopRight:
                case LegendPosition.BottomRight:
                    left = this.PlotArea.Right - legendSize.Width - this.LegendMargin;
                    break;

                case LegendPosition.LeftTop:
                case LegendPosition.RightTop:
                    top = this.PlotArea.Top + this.LegendMargin;
                    break;

                case LegendPosition.LeftBottom:
                case LegendPosition.RightBottom:
                    top = this.PlotArea.Bottom - legendSize.Height - this.LegendMargin;
                    break;

                case LegendPosition.LeftMiddle:
                case LegendPosition.RightMiddle:
                    top = (this.PlotArea.Top + this.PlotArea.Bottom - legendSize.Height) * 0.5;
                    break;

                case LegendPosition.TopCenter:
                case LegendPosition.BottomCenter:
                    left = (this.PlotArea.Left + this.PlotArea.Right - legendSize.Width) * 0.5;
                    break;
                }
            }

            return(new OxyRect(left, top, legendSize.Width, legendSize.Height));
        }
        /// <summary>
        /// The internal draw math text.
        /// </summary>
        /// <param name="rc">
        /// The render context.
        /// </param>
        /// <param name="x">
        /// The x.
        /// </param>
        /// <param name="y">
        /// The y.
        /// </param>
        /// <param name="s">
        /// The s.
        /// </param>
        /// <param name="textColor">
        /// The text color.
        /// </param>
        /// <param name="fontFamily">
        /// The font family.
        /// </param>
        /// <param name="fontSize">
        /// The font size.
        /// </param>
        /// <param name="fontWeight">
        /// The font weight.
        /// </param>
        /// <param name="measureOnly">
        /// The measure only.
        /// </param>
        /// <returns>
        /// The size of the text.
        /// </returns>
        private static OxySize InternalDrawMathText(
            IRenderContext rc,
            double x,
            double y,
            string s,
            OxyColor textColor,
            string fontFamily,
            double fontSize,
            double fontWeight,
            bool measureOnly)
        {
            int i = 0;

            double currentX  = x;
            double maximumX  = x;
            double maxHeight = 0;

            // http://en.wikipedia.org/wiki/Subscript_and_superscript
            double superscriptY        = y + fontSize * SuperAlignment;
            double superscriptFontSize = fontSize * SuperSize;
            double subscriptY          = y + fontSize * SubAlignment;
            double subscriptFontSize   = fontSize * SubSize;

            Func <double, double, string, double, OxySize> drawText = (xb, yb, text, fSize) =>
            {
                if (!measureOnly)
                {
                    rc.DrawText(new ScreenPoint(xb, yb), text, textColor, fontFamily, fSize, fontWeight);
                }

                return(rc.MeasureText(text, fontFamily, fSize, fontWeight));
            };

            while (i < s.Length)
            {
                // Superscript
                if (i + 1 < s.Length && s[i] == '^' && s[i + 1] == '{')
                {
                    int i1 = s.IndexOf('}', i);
                    if (i1 != -1)
                    {
                        string supString = s.Substring(i + 2, i1 - i - 2);
                        i = i1 + 1;
                        OxySize size = drawText(currentX, superscriptY, supString, superscriptFontSize);
                        if (currentX + size.Width > maximumX)
                        {
                            maximumX = currentX + size.Width;
                        }

                        continue;
                    }
                }

                // Subscript
                if (i + 1 < s.Length && s[i] == '_' && s[i + 1] == '{')
                {
                    int i1 = s.IndexOf('}', i);
                    if (i1 != -1)
                    {
                        string subString = s.Substring(i + 2, i1 - i - 2);
                        i = i1 + 1;
                        OxySize size = drawText(currentX, subscriptY, subString, subscriptFontSize);
                        if (currentX + size.Width > maximumX)
                        {
                            maximumX = currentX + size.Width;
                        }

                        continue;
                    }
                }

                // Regular text
                int    i2 = s.IndexOfAny("^_".ToCharArray(), i);
                string regularString;
                if (i2 == -1)
                {
                    regularString = s.Substring(i);
                    i             = s.Length;
                }
                else
                {
                    regularString = s.Substring(i, i2 - i);
                    i             = i2;
                }

                currentX = maximumX + 2;
                OxySize size2 = drawText(currentX, y, regularString, fontSize);
                currentX += size2.Width + 2;
                maxHeight = Math.Max(maxHeight, size2.Height);
                maximumX  = currentX;
            }

            return(new OxySize(maximumX - x, maxHeight));
        }
Пример #28
0
        /// <summary>
        /// Draws the text.
        /// </summary>
        /// <param name="p">The position of the text.</param>
        /// <param name="text">The text.</param>
        /// <param name="fill">The fill color.</param>
        /// <param name="fontFamily">The font family.</param>
        /// <param name="fontSize">Size of the font.</param>
        /// <param name="fontWeight">The font weight.</param>
        /// <param name="rotate">The rotation angle.</param>
        /// <param name="halign">The horizontal alignment.</param>
        /// <param name="valign">The vertical alignment.</param>
        /// <param name="maxSize">The maximum size of the text.</param>
        public override void DrawText(
            ScreenPoint p,
            string text,
            OxyColor fill,
            string fontFamily,
            double fontSize,
            double fontWeight,
            double rotate,
            HorizontalAlignment halign,
            VerticalAlignment valign,
            OxySize? maxSize)
        {
            this.doc.SaveState();
            this.doc.SetFont(fontFamily, fontSize / 96 * 72, fontWeight > 500);
            this.doc.SetFillColor(fill);

            double width, height;
            this.doc.MeasureText(text, out width, out height);
            if (maxSize != null)
            {
                if (width > maxSize.Value.Width)
                {
                    width = Math.Max(maxSize.Value.Width, 0);
                }

                if (height > maxSize.Value.Height)
                {
                    height = Math.Max(maxSize.Value.Height, 0);
                }
            }

            double dx = 0;
            if (halign == HorizontalAlignment.Center)
            {
                dx = -width / 2;
            }

            if (halign == HorizontalAlignment.Right)
            {
                dx = -width;
            }

            double dy = 0;

            if (valign == VerticalAlignment.Middle)
            {
                dy = -height / 2;
            }

            if (valign == VerticalAlignment.Top)
            {
                dy = -height;
            }

            double y = this.doc.PageHeight - p.Y;

            this.doc.Translate(p.X, y);
            if (Math.Abs(rotate) > 1e-6)
            {
                this.doc.Rotate(-rotate);
            }

            this.doc.Translate(dx, dy);

            // this.doc.DrawRectangle(0, 0, width, height);
            this.doc.SetClippingRectangle(0, 0, width, height);
            this.doc.DrawText(0, 0, text);
            this.doc.RestoreState();
        }
 /// <summary>
 /// Draws text containing sub- and superscript.
 /// </summary>
 /// <param name="rc">The render context.</param>
 /// <param name="pt">The point.</param>
 /// <param name="text">The text.</param>
 /// <param name="textColor">Color of the text.</param>
 /// <param name="fontFamily">The font family.</param>
 /// <param name="fontSize">The font size.</param>
 /// <param name="fontWeight">The font weight.</param>
 /// <param name="angle">The angle.</param>
 /// <param name="ha">The horizontal alignment.</param>
 /// <param name="va">The vertical alignment.</param>
 /// <param name="maxSize">The maximum size of the text.</param>
 /// <example>Subscript: H_{2}O
 /// Superscript: E=mc^{2}
 /// Both: A^{2}_{i,j}</example>
 public static void DrawMathText(
     this IRenderContext rc,
     ScreenPoint pt,
     string text,
     OxyColor textColor,
     string fontFamily,
     double fontSize,
     double fontWeight,
     double angle,
     HorizontalAlignment ha,
     VerticalAlignment va,
     OxySize? maxSize = null)
 {
     DrawMathText(rc, pt, text, textColor, fontFamily, fontSize, fontWeight, angle, ha, va, maxSize, false);
 }
Пример #30
0
 /// <summary>
 /// Draws the text.
 /// </summary>
 /// <param name="p">The position of the text.</param>
 /// <param name="text">The text.</param>
 /// <param name="fill">The fill color.</param>
 /// <param name="fontFamily">The font family.</param>
 /// <param name="fontSize">Size of the font.</param>
 /// <param name="fontWeight">The font weight.</param>
 /// <param name="rotate">The rotation angle.</param>
 /// <param name="halign">The horizontal alignment.</param>
 /// <param name="valign">The vertical alignment.</param>
 /// <param name="maxSize">The maximum size of the text.</param>
 public abstract void DrawText(
     ScreenPoint p,
     string text,
     OxyColor fill,
     string fontFamily,
     double fontSize,
     double fontWeight,
     double rotate,
     HorizontalAlignment halign,
     VerticalAlignment valign,
     OxySize? maxSize);
Пример #31
0
        /// <summary>
        /// Renders the legend for the specified series.
        /// </summary>
        /// <param name="rc">The render context.</param>
        /// <param name="s">The series.</param>
        /// <param name="rect">The position and size of the legend.</param>
        private void RenderLegend(IRenderContext rc, Series.Series s, OxyRect rect)
        {
            var actualItemAlignment = this.LegendItemAlignment;

            if (this.LegendOrientation == LegendOrientation.Horizontal)
            {
                // center/right alignment is not supported for horizontal orientation
                actualItemAlignment = HorizontalAlignment.Left;
            }

            double x = rect.Left;

            switch (actualItemAlignment)
            {
            case HorizontalAlignment.Center:
                x = (rect.Left + rect.Right) / 2;
                if (this.LegendSymbolPlacement == LegendSymbolPlacement.Left)
                {
                    x -= (this.LegendSymbolLength + this.LegendSymbolMargin) / 2;
                }
                else
                {
                    x -= (this.LegendSymbolLength + this.LegendSymbolMargin) / 2;
                }

                break;

            case HorizontalAlignment.Right:
                x = rect.Right;

                // if (LegendSymbolPlacement == LegendSymbolPlacement.Right)
                x -= this.LegendSymbolLength + this.LegendSymbolMargin;
                break;
            }

            if (this.LegendSymbolPlacement == LegendSymbolPlacement.Left)
            {
                x += this.LegendSymbolLength + this.LegendSymbolMargin;
            }

            double y       = rect.Top;
            var    maxsize = new OxySize(Math.Max(rect.Width - this.LegendSymbolLength - this.LegendSymbolMargin, 0), rect.Height);

            rc.SetToolTip(s.ToolTip);
            var textSize = rc.DrawMathText(
                new ScreenPoint(x, y),
                s.Title,
                this.LegendTextColor.GetActualColor(this.TextColor),
                this.LegendFont ?? this.DefaultFont,
                this.LegendFontSize,
                this.LegendFontWeight,
                0,
                actualItemAlignment,
                VerticalAlignment.Top,
                maxsize,
                true);
            double x0 = x;

            switch (actualItemAlignment)
            {
            case HorizontalAlignment.Center:
                x0 = x - (textSize.Width * 0.5);
                break;

            case HorizontalAlignment.Right:
                x0 = x - textSize.Width;
                break;
            }

            var symbolRect =
                new OxyRect(
                    this.LegendSymbolPlacement == LegendSymbolPlacement.Right
                        ? x0 + textSize.Width + this.LegendSymbolMargin
                        : x0 - this.LegendSymbolMargin - this.LegendSymbolLength,
                    rect.Top,
                    this.LegendSymbolLength,
                    textSize.Height);

            s.RenderLegend(rc, symbolRect);
            rc.SetToolTip(null);
        }
Пример #32
0
        /// <summary>
        /// Measures the size of the axis (maximum axis label width/height).
        /// </summary>
        /// <param name="rc">
        /// The render context.
        /// </param>
        /// <returns>
        /// The size of the axis.
        /// </returns>
        public virtual OxySize Measure(IRenderContext rc)
        {
            IList<double> majorTickValues;
            IList<double> minorTickValues;
            IList<double> majorLabelValues;

            this.GetTickValues(out majorLabelValues, out majorTickValues, out minorTickValues);

            var maximumTextSize = new OxySize();
            foreach (double v in majorLabelValues)
            {
                string s = this.FormatValue(v);
                var size = rc.MeasureText(s, this.ActualFont, this.ActualFontSize, this.ActualFontWeight);
                if (size.Width > maximumTextSize.Width)
                {
                    maximumTextSize.Width = size.Width;
                }

                if (size.Height > maximumTextSize.Height)
                {
                    maximumTextSize.Height = size.Height;
                }
            }

            var labelTextSize = rc.MeasureText(
                this.ActualTitle, this.ActualFont, this.ActualFontSize, this.ActualFontWeight);

            double width = 0;
            double height = 0;

            if (this.IsHorizontal())
            {
                switch (this.TickStyle)
                {
                    case TickStyle.Outside:
                        height += this.MajorTickSize;
                        break;
                    case TickStyle.Crossing:
                        height += this.MajorTickSize * 0.75;
                        break;
                }

                height += this.AxisTickToLabelDistance;
                height += maximumTextSize.Height;
                if (labelTextSize.Height > 0)
                {
                    height += this.AxisTitleDistance;
                    height += labelTextSize.Height;
                }
            }
            else
            {
                switch (this.TickStyle)
                {
                    case TickStyle.Outside:
                        width += this.MajorTickSize;
                        break;
                    case TickStyle.Crossing:
                        width += this.MajorTickSize * 0.75;
                        break;
                }

                width += this.AxisTickToLabelDistance;
                width += maximumTextSize.Width;
                if (labelTextSize.Height > 0)
                {
                    width += this.AxisTitleDistance;
                    width += labelTextSize.Height;
                }
            }

            return new OxySize(width, height);
        }
Пример #33
0
        /// <summary>
        /// Renders or measures the legends.
        /// </summary>
        /// <param name="rc">The render context.</param>
        /// <param name="rect">Provides the available size if measuring, otherwise it provides the position and size of the legend.</param>
        /// <param name="measureOnly">Specify if the size of the legend box should be measured only (not rendered).</param>
        /// <returns>The size of the legend box.</returns>
        private OxySize RenderOrMeasureLegends(IRenderContext rc, OxyRect rect, bool measureOnly = false)
        {
            // Render background and border around legend
            if (!measureOnly && rect.Width > 0 && rect.Height > 0)
            {
                rc.DrawRectangleAsPolygon(rect, this.LegendBackground, this.LegendBorder, this.LegendBorderThickness);
            }

            double availableWidth  = rect.Width;
            double availableHeight = rect.Height;

            double x   = this.LegendPadding;
            double top = this.LegendPadding;

            var size = new OxySize();

            // Render/measure the legend title
            if (!string.IsNullOrEmpty(this.LegendTitle))
            {
                OxySize titleSize;
                if (measureOnly)
                {
                    titleSize = rc.MeasureMathText(
                        this.LegendTitle,
                        this.LegendTitleFont ?? this.DefaultFont,
                        this.LegendTitleFontSize,
                        this.LegendTitleFontWeight);
                }
                else
                {
                    titleSize = rc.DrawMathText(
                        new ScreenPoint(rect.Left + x, rect.Top + top),
                        this.LegendTitle,
                        this.LegendTitleColor.GetActualColor(this.TextColor),
                        this.LegendTitleFont ?? this.DefaultFont,
                        this.LegendTitleFontSize,
                        this.LegendTitleFontWeight,
                        0,
                        HorizontalAlignment.Left,
                        VerticalAlignment.Top,
                        null,
                        true);
                }

                top += titleSize.Height;
                size = new OxySize(x + titleSize.Width + this.LegendPadding, top + titleSize.Height);
            }

            double y = top;

            double lineHeight = 0;

            // tolerance for floating-point number comparisons
            const double Epsilon = 1e-3;

            // the maximum item with in the column being rendered (only used for vertical orientation)
            double maxItemWidth = 0;

            var items = this.LegendItemOrder == LegendItemOrder.Reverse
                ? this.Series.Reverse().Where(s => s.IsVisible)
                : this.Series.Where(s => s.IsVisible);

            // When orientation is vertical and alignment is center or right, the items cannot be rendered before
            // the max item width has been calculated. Render the items for each column, and at the end.
            var    seriesToRender = new Dictionary <Series.Series, OxyRect>();
            Action renderItems    = () =>
            {
                foreach (var sr in seriesToRender)
                {
                    var itemRect   = sr.Value;
                    var itemSeries = sr.Key;

                    double rwidth = availableWidth;
                    if (itemRect.Left + rwidth + this.LegendPadding > rect.Left + availableWidth)
                    {
                        rwidth = rect.Left + availableWidth - itemRect.Left - this.LegendPadding;
                    }

                    double rheight = itemRect.Height;
                    if (rect.Top + rheight + this.LegendPadding > rect.Top + availableHeight)
                    {
                        rheight = rect.Top + availableHeight - rect.Top - this.LegendPadding;
                    }

                    var r = new OxyRect(itemRect.Left, itemRect.Top, Math.Max(rwidth, 0), Math.Max(rheight, 0));
                    this.RenderLegend(rc, itemSeries, r);
                }

                seriesToRender.Clear();
            };

            foreach (var s in items)
            {
                // Skip series with empty title
                if (string.IsNullOrEmpty(s.Title) || !s.RenderInLegend)
                {
                    continue;
                }

                var    textSize   = rc.MeasureMathText(s.Title, this.LegendFont ?? this.DefaultFont, this.LegendFontSize, this.LegendFontWeight);
                double itemWidth  = this.LegendSymbolLength + this.LegendSymbolMargin + textSize.Width;
                double itemHeight = textSize.Height;

                if (this.LegendOrientation == LegendOrientation.Horizontal)
                {
                    // Add spacing between items
                    if (x > this.LegendPadding)
                    {
                        x += this.LegendItemSpacing;
                    }

                    // Check if the item is too large to fit within the available width
                    if (x + itemWidth > availableWidth - this.LegendPadding + Epsilon)
                    {
                        // new line
                        x          = this.LegendPadding;
                        y         += lineHeight + this.LegendLineSpacing;
                        lineHeight = 0;
                    }

                    // Update the max size of the current line
                    lineHeight = Math.Max(lineHeight, textSize.Height);

                    if (!measureOnly)
                    {
                        seriesToRender.Add(s, new OxyRect(rect.Left + x, rect.Top + y, itemWidth, itemHeight));
                    }

                    x += itemWidth;

                    // Update the max width and height of the legend box
                    size = new OxySize(Math.Max(size.Width, x), Math.Max(size.Height, y + textSize.Height));
                }
                else
                {
                    if (y + itemHeight > availableHeight - this.LegendPadding + Epsilon)
                    {
                        renderItems();

                        y            = top;
                        x           += maxItemWidth + this.LegendColumnSpacing;
                        maxItemWidth = 0;
                    }

                    if (!measureOnly)
                    {
                        seriesToRender.Add(s, new OxyRect(rect.Left + x, rect.Top + y, itemWidth, itemHeight));
                    }

                    y += itemHeight + this.LegendLineSpacing;

                    // Update the max size of the items in the current column
                    maxItemWidth = Math.Max(maxItemWidth, itemWidth);

                    // Update the max width and height of the legend box
                    size = new OxySize(Math.Max(size.Width, x + itemWidth), Math.Max(size.Height, y));
                }
            }

            renderItems();

            if (size.Width > 0)
            {
                size = new OxySize(size.Width + this.LegendPadding, size.Height);
            }

            if (size.Height > 0)
            {
                size = new OxySize(size.Width, size.Height + this.LegendPadding);
            }

            if (size.Width > availableWidth)
            {
                size = new OxySize(availableWidth, size.Height);
            }

            if (size.Height > availableHeight)
            {
                size = new OxySize(size.Width, availableHeight);
            }

            if (!double.IsNaN(this.LegendMaxWidth) && size.Width > this.LegendMaxWidth)
            {
                size = new OxySize(this.LegendMaxWidth, size.Height);
            }

            if (!double.IsNaN(this.LegendMaxHeight) && size.Height > this.LegendMaxHeight)
            {
                size = new OxySize(size.Width, this.LegendMaxHeight);
            }

            return(size);
        }
Пример #34
0
        public static PlotModel DrawTextMaxSize()
        {
            var model = new PlotModel();
            model.Annotations.Add(new DelegateAnnotation(rc =>
                {
                    const string Font = "Arial";
                    const double FontSize = 32d;
                    const double FontWeight = FontWeights.Bold;
                    const double D = FontSize * 1.6;
                    const double X = 20;
                    const double X2 = 200;
                    double y = 20;
                    var testStrings = new[] { "iii", "jjj", "OxyPlot", "Bottom", "100", "KML" };
                    foreach (var text in testStrings)
                    {
                        var maxSize = rc.MeasureText(text, Font, FontSize, FontWeight);
                        var p = new ScreenPoint(X, y);
                        rc.DrawText(p, text, OxyColors.Black, Font, FontSize, FontWeight, maxSize: maxSize);
                        var rect = new OxyRect(p, maxSize);
                        rc.DrawRectangle(rect, OxyColors.Undefined, OxyColors.Black);

                        var p2 = new ScreenPoint(X2, y);
                        var maxSize2 = new OxySize(maxSize.Width / 2, maxSize.Height / 2);
                        rc.DrawText(p2, text, OxyColors.Black, Font, FontSize, FontWeight, maxSize: maxSize2);
                        var rect2 = new OxyRect(p2, maxSize2);
                        rc.DrawRectangle(rect2, OxyColors.Undefined, OxyColors.Black);

                        y += D;
                    }
                }));
            return model;
        }
Пример #35
0
        /// <summary>
        ///     Renders the series on the specified render context.
        /// </summary>
        /// <param name="rc">The rendering context.</param>
        /// <param name="model">The model.</param>
        public override void Render(IRenderContext rc, PlotModel model)
        {
            if (this.XAxis == null)
            {
                return;
            }

            this.symbolPosition = model.PlotArea.Bottom;
            this.symbolSize = rc.MeasureText(this.Symbol, this.FontFamily, this.FontSize);
            foreach (var v in this.Values)
            {
                if (double.IsNaN(v) || v < this.XAxis.ActualMinimum || v > this.XAxis.ActualMaximum)
                {
                    continue;
                }

                double x = this.XAxis.Transform(v);
                rc.DrawText(
                    new ScreenPoint(x, this.symbolPosition),
                    this.Symbol,
                    this.Color,
                    this.FontFamily,
                    this.FontSize,
                    FontWeights.Normal,
                    0,
                    HorizontalAlignment.Center,
                    VerticalAlignment.Bottom);
            }
        }
Пример #36
0
        /// <summary>
        /// Draws text with metrics.
        /// </summary>
        /// <param name="text">The text.</param>
        /// <param name="font">The font.</param>
        /// <param name="fontSize">Size of the font.</param>
        /// <param name="expectedWidth">The expected width.</param>
        /// <param name="expectedHeight">The expected height.</param>
        /// <param name="baseline">The baseline position.</param>
        /// <param name="xheight">The x-height position.</param>
        /// <param name="ascent">The ascent position.</param>
        /// <param name="descent">The descent position.</param>
        /// <param name="before">The before position.</param>
        /// <param name="after">The after position.</param>
        /// <param name="platform">The platform.</param>
        /// <returns>
        /// A plot model.
        /// </returns>
        private static PlotModel DrawTextWithMetrics(string text, string font, double fontSize, double expectedWidth, double expectedHeight, double baseline, double xheight, double ascent, double descent, double before, double after, string platform)
        {
            // http://msdn.microsoft.com/en-us/library/ms742190(v=vs.110).aspx
            // http://msdn.microsoft.com/en-us/library/xwf9s90b(v=vs.110).aspx
            // http://msdn.microsoft.com/en-us/library/windows/desktop/ms533824(v=vs.85).aspx
            // https://developer.apple.com/library/mac/documentation/TextFonts/Conceptual/CocoaTextArchitecture/FontHandling/FontHandling.html
            var model = new PlotModel();
            model.Annotations.Add(
                new DelegateAnnotation(
                    rc =>
                    {
                        var size = rc.MeasureText(text, font, fontSize);
                        var expectedSize = new OxySize(expectedWidth, expectedHeight);
                        rc.DrawText(new ScreenPoint(300, 50), "Font size: " + fontSize, OxyColors.Black, font, 12);
                        rc.DrawText(new ScreenPoint(300, 70), "Actual size: " + size.ToString("0.00", CultureInfo.InvariantCulture), OxyColors.Black, font, 12);
                        rc.DrawText(new ScreenPoint(300, 90), "Size on " + platform + ": " + expectedSize.ToString("0.00", CultureInfo.InvariantCulture), OxyColors.Green, font, 12);

                        var p = new ScreenPoint(20, 50);
                        rc.DrawText(p, text, OxyColors.Black, font, fontSize);

                        rc.FillCircle(p, 3, OxyColors.Black);

                        // actual bounds
                        rc.DrawRectangle(new OxyRect(p, size), OxyColors.Undefined, OxyColors.Black);

                        // Expected bounds (WPF)
                        rc.DrawRectangle(new OxyRect(p, expectedSize), OxyColors.Undefined, OxyColors.Green);

                        var color = OxyColor.FromAColor(180, OxyColors.Red);
                        var pen = new OxyPen(color);

                        // Expected vertical positions (WPF)
                        var x1 = p.X - 10;
                        var x2 = p.X + expectedSize.Width + 10;
                        rc.DrawLine(x1, baseline, x2, baseline, pen);
                        rc.DrawLine(x1, xheight, x2, xheight, pen);
                        rc.DrawLine(x1, ascent, x2, ascent, pen);
                        rc.DrawLine(x1, descent, x2, descent, pen);

                        // Expected horizonal positions (WPF)
                        var y1 = p.Y - 10;
                        var y2 = p.Y + expectedSize.Height + 10;
                        rc.DrawLine(before, y1, before, y2, pen);
                        rc.DrawLine(after, y1, after, y2, pen);
                    }));

            model.MouseDown += (s, e) => Debug.WriteLine(e.Position);

            return model;
        }
Пример #37
0
 /// <summary>
 /// Measures the legends.
 /// </summary>
 /// <param name="rc">The render context.</param>
 /// <param name="availableSize">The available size for the legend box.</param>
 /// <returns>The size of the legend box.</returns>
 private OxySize MeasureLegends(IRenderContext rc, OxySize availableSize)
 {
     return this.RenderOrMeasureLegends(rc, new OxyRect(0, 0, availableSize.Width, availableSize.Height), true);
 }
        /// <summary>
        /// Gets the coordinates of the (rotated) background rectangle.
        /// </summary>
        /// <param name="position">
        /// The position.
        /// </param>
        /// <param name="size">
        /// The size.
        /// </param>
        /// <param name="padding">
        /// The padding.
        /// </param>
        /// <param name="rotation">
        /// The rotation.
        /// </param>
        /// <param name="horizontalAlignment">
        /// The horizontal alignment.
        /// </param>
        /// <param name="verticalAlignment">
        /// The vertical alignment.
        /// </param>
        /// <returns>
        /// The background rectangle coordinates.
        /// </returns>
        private static IList<ScreenPoint> GetTextBounds(
            ScreenPoint position,
            OxySize size,
            OxyThickness padding,
            double rotation,
            HorizontalTextAlign horizontalAlignment,
            VerticalTextAlign verticalAlignment)
        {
            double left, right, top, bottom;
            switch (horizontalAlignment)
            {
                case HorizontalTextAlign.Center:
                    left = -size.Width * 0.5;
                    right = -left;
                    break;
                case HorizontalTextAlign.Right:
                    left = -size.Width;
                    right = 0;
                    break;
                default:
                    left = 0;
                    right = size.Width;
                    break;
            }

            switch (verticalAlignment)
            {
                case VerticalTextAlign.Middle:
                    top = -size.Height * 0.5;
                    bottom = -top;
                    break;
                case VerticalTextAlign.Bottom:
                    top = -size.Height;
                    bottom = 0;
                    break;
                default:
                    top = 0;
                    bottom = size.Height;
                    break;
            }

            double cost = Math.Cos(rotation / 180 * Math.PI);
            double sint = Math.Sin(rotation / 180 * Math.PI);
            var u = new ScreenVector(cost, sint);
            var v = new ScreenVector(-sint, cost);
            var polygon = new ScreenPoint[4];
            polygon[0] = position + u * (left - padding.Left) + v * (top - padding.Top);
            polygon[1] = position + u * (right + padding.Right) + v * (top - padding.Top);
            polygon[2] = position + u * (right + padding.Right) + v * (bottom + padding.Bottom);
            polygon[3] = position + u * (left - padding.Left) + v * (bottom + padding.Bottom);
            return polygon;
        }
Пример #39
0
        /// <summary>
        /// Renders or measures the legends.
        /// </summary>
        /// <param name="rc">The render context.</param>
        /// <param name="rect">Provides the available size if measuring, otherwise it provides the position and size of the legend.</param>
        /// <param name="measureOnly">Specify if the size of the legend box should be measured only (not rendered).</param>
        /// <returns>The size of the legend box.</returns>
        private OxySize RenderOrMeasureLegends(IRenderContext rc, OxyRect rect, bool measureOnly = false)
        {
            // Render background and border around legend
            if (!measureOnly && rect.Width > 0 && rect.Height > 0)
            {
                rc.DrawRectangleAsPolygon(rect, this.LegendBackground, this.LegendBorder, this.LegendBorderThickness);
            }

            double availableWidth = rect.Width;
            double availableHeight = rect.Height;

            double x = this.LegendPadding;
            double top = this.LegendPadding;

            var size = new OxySize();

            // Render/measure the legend title
            if (!string.IsNullOrEmpty(this.LegendTitle))
            {
                OxySize titleSize;
                if (measureOnly)
                {
                    titleSize = rc.MeasureMathText(
                        this.LegendTitle,
                        this.LegendTitleFont ?? this.DefaultFont,
                        this.LegendTitleFontSize,
                        this.LegendTitleFontWeight);
                }
                else
                {
                    titleSize = rc.DrawMathText(
                        new ScreenPoint(rect.Left + x, rect.Top + top),
                        this.LegendTitle,
                        this.LegendTitleColor.GetActualColor(this.TextColor),
                        this.LegendTitleFont ?? this.DefaultFont,
                        this.LegendTitleFontSize,
                        this.LegendTitleFontWeight,
                        0,
                        HorizontalAlignment.Left,
                        VerticalAlignment.Top,
                        null,
                        true);
                }

                top += titleSize.Height;
                size.Width = x + titleSize.Width + this.LegendPadding;
                size.Height = top + titleSize.Height;
            }

            double y = top;

            double lineHeight = 0;

            // tolerance for floating-point number comparisons
            const double Epsilon = 1e-3;

            // the maximum item with in the column being rendered (only used for vertical orientation)
            double maxItemWidth = 0;

            var items = this.LegendItemOrder == LegendItemOrder.Reverse
                ? this.Series.Reverse().Where(s => s.IsVisible)
                : this.Series.Where(s => s.IsVisible);

            // When orientation is vertical and alignment is center or right, the items cannot be rendered before
            // the max item width has been calculated. Render the items for each column, and at the end.
            var seriesToRender = new Dictionary<Series.Series, OxyRect>();
            Action renderItems = () =>
                {
                    foreach (var sr in seriesToRender)
                    {
                        var itemRect = sr.Value;
                        var itemSeries = sr.Key;

                        double rwidth = availableWidth;
                        if (itemRect.Left + rwidth + this.LegendPadding > rect.Left + availableWidth)
                        {
                            rwidth = rect.Left + availableWidth - itemRect.Left - this.LegendPadding;
                        }

                        double rheight = itemRect.Height;
                        if (rect.Top + rheight + this.LegendPadding > rect.Top + availableHeight)
                        {
                            rheight = rect.Top + availableHeight - rect.Top - this.LegendPadding;
                        }

                        var r = new OxyRect(itemRect.Left, itemRect.Top, Math.Max(rwidth, 0), Math.Max(rheight, 0));
                        this.RenderLegend(rc, itemSeries, r);
                    }

                    seriesToRender.Clear();
                };

            foreach (var s in items)
            {
                // Skip series with empty title
                if (string.IsNullOrEmpty(s.Title))
                {
                    continue;
                }

                var textSize = rc.MeasureMathText(s.Title, this.LegendFont ?? this.DefaultFont, this.LegendFontSize, this.LegendFontWeight);
                double itemWidth = this.LegendSymbolLength + this.LegendSymbolMargin + textSize.Width;
                double itemHeight = textSize.Height;

                if (this.LegendOrientation == LegendOrientation.Horizontal)
                {
                    // Add spacing between items
                    if (x > this.LegendPadding)
                    {
                        x += this.LegendItemSpacing;
                    }

                    // Check if the item is too large to fit within the available width
                    if (x + itemWidth > availableWidth - this.LegendPadding + Epsilon)
                    {
                        // new line
                        x = this.LegendPadding;
                        y += lineHeight;
                        lineHeight = 0;
                    }

                    // Update the max size of the current line
                    lineHeight = Math.Max(lineHeight, textSize.Height);

                    if (!measureOnly)
                    {
                        seriesToRender.Add(s, new OxyRect(rect.Left + x, rect.Top + y, itemWidth, itemHeight));
                    }

                    x += itemWidth;

                    // Update the max width of the legend box
                    size.Width = Math.Max(size.Width, x);

                    // Update the max height of the legend box
                    size.Height = Math.Max(size.Height, y + textSize.Height);
                }
                else
                {
                    if (y + itemHeight > availableHeight - this.LegendPadding + Epsilon)
                    {
                        renderItems();

                        y = top;
                        x += maxItemWidth + this.LegendColumnSpacing;
                        maxItemWidth = 0;
                    }

                    if (!measureOnly)
                    {
                        seriesToRender.Add(s, new OxyRect(rect.Left + x, rect.Top + y, itemWidth, itemHeight));
                    }

                    y += itemHeight;

                    // Update the max size of the items in the current column
                    maxItemWidth = Math.Max(maxItemWidth, itemWidth);

                    // Update the max width of the legend box
                    size.Width = Math.Max(size.Width, x + itemWidth);

                    // Update the max height of the legend box
                    size.Height = Math.Max(size.Height, y);
                }
            }

            renderItems();

            if (size.Width > 0)
            {
                size.Width += this.LegendPadding;
            }

            if (size.Height > 0)
            {
                size.Height += this.LegendPadding;
            }

            if (size.Width > availableWidth)
            {
                size.Width = availableWidth;
            }

            if (size.Height > availableHeight)
            {
                size.Height = availableHeight;
            }

            if (!double.IsNaN(this.LegendMaxWidth) && size.Width > this.LegendMaxWidth)
            {
                size.Width = this.LegendMaxWidth;
            }

            return size;
        }
Пример #40
0
        /// <summary>
        /// Draws the text.
        /// </summary>
        /// <param name="p">The p.</param>
        /// <param name="text">The text.</param>
        /// <param name="c">The c.</param>
        /// <param name="fontFamily">The font family.</param>
        /// <param name="fontSize">Size of the font.</param>
        /// <param name="fontWeight">The font weight.</param>
        /// <param name="rotate">The rotate.</param>
        /// <param name="halign">The horizontal alignment.</param>
        /// <param name="valign">The vertical alignment.</param>
        /// <param name="maxSize">Size of the max.</param>
        public override void DrawText(
            ScreenPoint p,
            string text,
            OxyColor c,
            string fontFamily,
            double fontSize,
            double fontWeight,
            double rotate,
            HorizontalAlignment halign,
            VerticalAlignment valign,
            OxySize? maxSize)
        {
            if (string.IsNullOrEmpty(text))
            {
                return;
            }

            var lines = Regex.Split(text, "\r\n");
            if (valign == VerticalAlignment.Bottom)
            {
                for (var i = lines.Length - 1; i >= 0; i--)
                {
                    var line = lines[i];
                    var size = this.MeasureText(line, fontFamily, fontSize, fontWeight);
                    this.w.WriteText(p, line, c, fontFamily, fontSize, fontWeight, rotate, halign, valign);

                    p.X += Math.Sin(rotate / 180.0 * Math.PI) * size.Height;
                    p.Y -= Math.Cos(rotate / 180.0 * Math.PI) * size.Height;
                }
            }
            else
            {
                foreach (var line in lines)
                {
                    var size = this.MeasureText(line, fontFamily, fontSize, fontWeight);
                    this.w.WriteText(p, line, c, fontFamily, fontSize, fontWeight, rotate, halign, valign);

                    p.X -= Math.Sin(rotate / 180.0 * Math.PI) * size.Height;
                    p.Y += Math.Cos(rotate / 180.0 * Math.PI) * size.Height;
                }
            }
        }
        /// <summary>
        /// The measure string.
        /// </summary>
        /// <param name="faceName">
        /// The font face name.
        /// </param>
        /// <param name="height">
        /// The height.
        /// </param>
        /// <param name="weight">
        /// The weight.
        /// </param>
        /// <param name="str">
        /// The string.
        /// </param>
        /// <returns>
        /// The size of the rendered string.
        /// </returns>
        public static OxySize MeasureString(string faceName, int height, int weight, string str)
        {
            var lines = Regex.Split(str, "\r\n");
            OxySize result = new OxySize(0, 0);
            foreach (var line in lines)
            {
                var hfont = CreateFont(height, 0, 0, 0, weight, 0, 0, 0, 0, 0, 0, 0, 0, faceName);
                var hdc = GetDC(IntPtr.Zero);
                var oldobj = SelectObject(hdc, hfont);
                var temp = GetTextExtent(hdc, line);
                SelectObject(hdc, oldobj);
                DeleteObject(hfont);
                DeleteDC(hdc);
                var lineSpacing = temp.Height / 3.0;
                result.Height += temp.Height + lineSpacing;
                result.Width = Math.Max(temp.Width * 1.28, result.Width);
            }

            return result;
        }
Пример #42
0
        /// <summary>
        /// Draws the text.
        /// </summary>
        /// <param name="p">The p.</param>
        /// <param name="text">The text.</param>
        /// <param name="fill">The fill color.</param>
        /// <param name="fontFamily">The font family.</param>
        /// <param name="fontSize">Size of the font.</param>
        /// <param name="fontWeight">The font weight.</param>
        /// <param name="rotate">The rotation angle.</param>
        /// <param name="halign">The horizontal alignment.</param>
        /// <param name="valign">The vertical alignment.</param>
        /// <param name="maxSize">The maximum size of the text.</param>
        public override void DrawText(
            ScreenPoint p,
            string text,
            OxyColor fill,
            string fontFamily,
            double fontSize,
            double fontWeight,
            double rotate,
            HorizontalAlignment halign,
            VerticalAlignment valign,
            OxySize? maxSize)
        {
            if (text == null)
            {
                return;
            }

            var fontStyle = fontWeight < 700 ? FontStyle.Regular : FontStyle.Bold;

            using (var font = CreateFont(fontFamily, fontSize, fontStyle))
            {
                this.stringFormat.Alignment = StringAlignment.Near;
                this.stringFormat.LineAlignment = StringAlignment.Near;
                var size = this.g.MeasureString(text, font, int.MaxValue, this.stringFormat);
                if (maxSize != null)
                {
                    if (size.Width > maxSize.Value.Width)
                    {
                        size.Width = (float)maxSize.Value.Width;
                    }

                    if (size.Height > maxSize.Value.Height)
                    {
                        size.Height = (float)maxSize.Value.Height;
                    }
                }

                float dx = 0;
                if (halign == HorizontalAlignment.Center)
                {
                    dx = -size.Width / 2;
                }

                if (halign == HorizontalAlignment.Right)
                {
                    dx = -size.Width;
                }

                float dy = 0;
                this.stringFormat.LineAlignment = StringAlignment.Near;
                if (valign == VerticalAlignment.Middle)
                {
                    dy = -size.Height / 2;
                }

                if (valign == VerticalAlignment.Bottom)
                {
                    dy = -size.Height;
                }

                var graphicsState = this.g.Save();

                this.g.TranslateTransform((float)p.X, (float)p.Y);

                var layoutRectangle = new RectangleF(0, 0, size.Width, size.Height);
                if (Math.Abs(rotate) > double.Epsilon)
                {
                    this.g.RotateTransform((float)rotate);

                    layoutRectangle.Height += (float)(fontSize / 18.0);
                }

                this.g.TranslateTransform(dx, dy);

                this.g.DrawString(text, font, fill.ToBrush(), layoutRectangle, this.stringFormat);

                this.g.Restore(graphicsState);
            }
        }
Пример #43
0
 /// <summary>
 /// Initializes a new instance of the <see cref="OxyRect"/> struct by location and size.
 /// </summary>
 /// <param name="p0">The location.</param>
 /// <param name="size">The size.</param>
 public OxyRect(ScreenPoint p0, OxySize size)
     : this(p0.X, p0.Y, size.Width, size.Height)
 {
 }
Пример #44
0
        /// <summary>
        /// Calculates the plot area (subtract padding, title size and outside legends)
        /// </summary>
        /// <param name="rc">The rendering context.</param>
        private void UpdatePlotArea(IRenderContext rc)
        {
            var plotArea = new OxyRect(
                this.PlotBounds.Left + this.Padding.Left,
                this.PlotBounds.Top + this.Padding.Top,
                Math.Max(0, this.Width - this.Padding.Left - this.Padding.Right),
                Math.Max(0, this.Height - this.Padding.Top - this.Padding.Bottom));

            var titleSize = this.MeasureTitles(rc);

            if (titleSize.Height > 0)
            {
                var titleHeight = titleSize.Height + this.TitlePadding;
                plotArea = new OxyRect(plotArea.Left, plotArea.Top + titleHeight, plotArea.Width, Math.Max(0, plotArea.Height - titleHeight));
            }

            plotArea = plotArea.Deflate(this.ActualPlotMargins);

            if (this.IsLegendVisible)
            {
                // Make space for legends

                OxySize maxLegendSize = new OxySize(0, 0);
                double  legendMargin  = 0;
                // first run Outside Left-Side legends
                foreach (var legend in this.Legends.Where(l =>
                                                          l.LegendPlacement == LegendPlacement.Outside && (l.IsLegendVisible &&
                                                                                                           (l.LegendPosition == LegendPosition.LeftTop || l.LegendPosition == LegendPosition.LeftMiddle || l.LegendPosition == LegendPosition.LeftBottom))))
                {
                    // Find the available size for the legend box
                    var availableLegendWidth  = plotArea.Width;
                    var availableLegendHeight = double.IsNaN(legend.LegendMaxHeight) ?
                                                plotArea.Height : Math.Min(plotArea.Height, legend.LegendMaxHeight);

                    var lsiz = legend.GetLegendSize(rc, new OxySize(availableLegendWidth, availableLegendHeight));
                    legend.LegendSize = lsiz;
                    maxLegendSize     = new OxySize(maxLegendSize.Width > lsiz.Width ? maxLegendSize.Width : lsiz.Width, maxLegendSize.Height > lsiz.Height ? maxLegendSize.Height : lsiz.Height);

                    if (legend.LegendMargin > legendMargin)
                    {
                        legendMargin = legend.LegendMargin;
                    }
                }

                // Adjust the plot area after the size of the legend has been calculated
                if (maxLegendSize.Width > 0 || maxLegendSize.Height > 0)
                {
                    plotArea = new OxyRect(plotArea.Left + maxLegendSize.Width + legendMargin, plotArea.Top, Math.Max(0, plotArea.Width - (maxLegendSize.Width + legendMargin)), plotArea.Height);
                }

                maxLegendSize = new OxySize(0, 0);
                legendMargin  = 0;
                // second run Outside Right-Side legends
                foreach (var legend in this.Legends.Where(l =>
                                                          l.LegendPlacement == LegendPlacement.Outside && (l.IsLegendVisible &&
                                                                                                           (l.LegendPosition == LegendPosition.RightTop || l.LegendPosition == LegendPosition.RightMiddle || l.LegendPosition == LegendPosition.RightBottom))))
                {
                    // Find the available size for the legend box
                    var availableLegendWidth  = plotArea.Width;
                    var availableLegendHeight = double.IsNaN(legend.LegendMaxHeight) ?
                                                plotArea.Height : Math.Min(plotArea.Height, legend.LegendMaxHeight);

                    var lsiz = legend.GetLegendSize(rc, new OxySize(availableLegendWidth, availableLegendHeight));
                    legend.LegendSize = lsiz;
                    maxLegendSize     = new OxySize(maxLegendSize.Width > lsiz.Width ? maxLegendSize.Width : lsiz.Width, maxLegendSize.Height > lsiz.Height ? maxLegendSize.Height : lsiz.Height);

                    if (legend.LegendMargin > legendMargin)
                    {
                        legendMargin = legend.LegendMargin;
                    }
                }

                // Adjust the plot area after the size of the legend has been calculated
                if (maxLegendSize.Width > 0 || maxLegendSize.Height > 0)
                {
                    plotArea = new OxyRect(plotArea.Left, plotArea.Top, Math.Max(0, plotArea.Width - (maxLegendSize.Width + legendMargin)), plotArea.Height);
                }

                maxLegendSize = new OxySize(0, 0);
                legendMargin  = 0;
                // third run Outside Top legends
                foreach (var legend in this.Legends.Where(l =>
                                                          l.LegendPlacement == LegendPlacement.Outside && (l.IsLegendVisible &&
                                                                                                           (l.LegendPosition == LegendPosition.TopLeft || l.LegendPosition == LegendPosition.TopCenter || l.LegendPosition == LegendPosition.TopRight))))
                {
                    // Find the available size for the legend box
                    var availableLegendWidth  = plotArea.Width;
                    var availableLegendHeight = double.IsNaN(legend.LegendMaxHeight) ?
                                                plotArea.Height : Math.Min(plotArea.Height, legend.LegendMaxHeight);

                    var lsiz = legend.GetLegendSize(rc, new OxySize(availableLegendWidth, availableLegendHeight));
                    legend.LegendSize = lsiz;
                    maxLegendSize     = new OxySize(maxLegendSize.Width > lsiz.Width ? maxLegendSize.Width : lsiz.Width, maxLegendSize.Height > lsiz.Height ? maxLegendSize.Height : lsiz.Height);

                    if (legend.LegendMargin > legendMargin)
                    {
                        legendMargin = legend.LegendMargin;
                    }
                }

                // Adjust the plot area after the size of the legend has been calculated
                if (maxLegendSize.Width > 0 || maxLegendSize.Height > 0)
                {
                    plotArea = new OxyRect(plotArea.Left, plotArea.Top + maxLegendSize.Height + legendMargin, plotArea.Width, Math.Max(0, plotArea.Height - (maxLegendSize.Height + legendMargin)));
                }

                maxLegendSize = new OxySize(0, 0);
                legendMargin  = 0;
                // fourth run Outside Bottom legends
                foreach (var legend in this.Legends.Where(l =>
                                                          l.LegendPlacement == LegendPlacement.Outside && (l.IsLegendVisible &&
                                                                                                           (l.LegendPosition == LegendPosition.BottomLeft || l.LegendPosition == LegendPosition.BottomCenter || l.LegendPosition == LegendPosition.BottomRight))))
                {
                    // Find the available size for the legend box
                    var availableLegendWidth  = plotArea.Width;
                    var availableLegendHeight = double.IsNaN(legend.LegendMaxHeight) ?
                                                plotArea.Height : Math.Min(plotArea.Height, legend.LegendMaxHeight);

                    var lsiz = legend.GetLegendSize(rc, new OxySize(availableLegendWidth, availableLegendHeight));
                    legend.LegendSize = lsiz;
                    maxLegendSize     = new OxySize(maxLegendSize.Width > lsiz.Width ? maxLegendSize.Width : lsiz.Width, maxLegendSize.Height > lsiz.Height ? maxLegendSize.Height : lsiz.Height);

                    if (legend.LegendMargin > legendMargin)
                    {
                        legendMargin = legend.LegendMargin;
                    }
                }

                // Adjust the plot area after the size of the legend has been calculated
                if (maxLegendSize.Width > 0 || maxLegendSize.Height > 0)
                {
                    plotArea = new OxyRect(plotArea.Left, plotArea.Top, plotArea.Width, Math.Max(0, plotArea.Height - (maxLegendSize.Height + legendMargin)));
                }

                // Finally calculate size of inside legends
                foreach (var legend in this.Legends.Where(l => l.LegendPlacement == LegendPlacement.Inside && l.IsLegendVisible))
                {
                    // Find the available size for the legend box
                    var availableLegendWidth  = plotArea.Width;
                    var availableLegendHeight = double.IsNaN(legend.LegendMaxHeight) ?
                                                plotArea.Height : Math.Min(plotArea.Height, legend.LegendMaxHeight);

                    if (legend.LegendPlacement == LegendPlacement.Inside)
                    {
                        availableLegendWidth  -= legend.LegendMargin * 2;
                        availableLegendHeight -= legend.LegendMargin * 2;
                    }

                    legend.LegendSize = legend.GetLegendSize(rc, new OxySize(availableLegendWidth, availableLegendHeight));
                }
            }

            // Ensure the plot area is valid
            if (plotArea.Height < 0)
            {
                plotArea = new OxyRect(plotArea.Left, plotArea.Top, plotArea.Width, 1);
            }

            if (plotArea.Width < 0)
            {
                plotArea = new OxyRect(plotArea.Left, plotArea.Top, 1, plotArea.Height);
            }

            this.PlotArea        = plotArea;
            this.PlotAndAxisArea = plotArea.Inflate(this.ActualPlotMargins);

            switch (this.TitleHorizontalAlignment)
            {
            case TitleHorizontalAlignment.CenteredWithinView:
                this.TitleArea = new OxyRect(
                    this.PlotBounds.Left,
                    this.PlotBounds.Top + this.Padding.Top,
                    this.Width,
                    titleSize.Height + (this.TitlePadding * 2));
                break;

            default:
                this.TitleArea = new OxyRect(
                    this.PlotArea.Left,
                    this.PlotBounds.Top + this.Padding.Top,
                    this.PlotArea.Width,
                    titleSize.Height + (this.TitlePadding * 2));
                break;
            }

            // Calculate the legend area for each legend.
            foreach (var l in this.Legends)
            {
                l.LegendArea = l.GetLegendRectangle(l.LegendSize);
            }
        }