ASCU_ALL/MigraDoc.Rendering/Rendering/ChartRenderer.cs
2020-09-04 12:49:15 +05:00

369 lines
14 KiB
C#

#region MigraDoc - Creating Documents on the Fly
//
// Authors:
// Klaus Potzesny
//
// Copyright (c) 2001-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.com
// http://www.migradoc.com
// http://sourceforge.net/projects/pdfsharp
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#endregion
using MigraDoc.DocumentObjectModel.publics;
using MigraDoc.DocumentObjectModel.Tables;
using PdfSharp.Drawing;
using MigraDoc.DocumentObjectModel.Shapes;
using MigraDoc.DocumentObjectModel.Shapes.Charts;
namespace MigraDoc.Rendering
{
/// <summary>
/// Renders a chart to an XGraphics object.
/// </summary>
public class ChartRenderer : ShapeRenderer
{
public ChartRenderer(XGraphics gfx, Chart chart, FieldInfos fieldInfos)
: base(gfx, chart, fieldInfos)
{
_chart = chart;
ChartRenderInfo renderInfo = new ChartRenderInfo();
renderInfo.DocumentObject = _shape;
_renderInfo = renderInfo;
}
public ChartRenderer(XGraphics gfx, RenderInfo renderInfo, FieldInfos fieldInfos)
: base(gfx, renderInfo, fieldInfos)
{
_chart = (Chart)renderInfo.DocumentObject;
}
FormattedTextArea GetFormattedTextArea(TextArea area, XUnit width)
{
if (area == null)
return null;
FormattedTextArea formattedTextArea = new FormattedTextArea(_documentRenderer, area, _fieldInfos);
if (!double.IsNaN(width))
formattedTextArea.InnerWidth = width;
formattedTextArea.Format(_gfx);
return formattedTextArea;
}
FormattedTextArea GetFormattedTextArea(TextArea area)
{
return GetFormattedTextArea(area, double.NaN);
}
void GetLeftRightVerticalPosition(out XUnit top, out XUnit bottom)
{
//REM: Line width is still ignored while layouting charts.
Area contentArea = _renderInfo.LayoutInfo.ContentArea;
ChartFormatInfo formatInfo = (ChartFormatInfo)_renderInfo.FormatInfo;
top = contentArea.Y;
if (formatInfo.FormattedHeader != null)
top += formatInfo.FormattedHeader.InnerHeight;
bottom = contentArea.Y + contentArea.Height;
if (formatInfo.FormattedFooter != null)
bottom -= formatInfo.FormattedFooter.InnerHeight;
}
Rectangle GetLeftRect()
{
Area contentArea = _renderInfo.LayoutInfo.ContentArea;
ChartFormatInfo formatInfo = (ChartFormatInfo)_renderInfo.FormatInfo;
XUnit top;
XUnit bottom;
GetLeftRightVerticalPosition(out top, out bottom);
XUnit left = contentArea.X;
XUnit width = formatInfo.FormattedLeft.InnerWidth;
return new Rectangle(left, top, width, bottom - top);
}
Rectangle GetRightRect()
{
Area contentArea = _renderInfo.LayoutInfo.ContentArea;
ChartFormatInfo formatInfo = (ChartFormatInfo)_renderInfo.FormatInfo;
XUnit top;
XUnit bottom;
GetLeftRightVerticalPosition(out top, out bottom);
XUnit left = contentArea.X + contentArea.Width - formatInfo.FormattedRight.InnerWidth;
XUnit width = formatInfo.FormattedRight.InnerWidth;
return new Rectangle(left, top, width, bottom - top);
}
Rectangle GetHeaderRect()
{
Area contentArea = _renderInfo.LayoutInfo.ContentArea;
ChartFormatInfo formatInfo = (ChartFormatInfo)_renderInfo.FormatInfo;
XUnit left = contentArea.X;
XUnit top = contentArea.Y;
XUnit width = contentArea.Width;
XUnit height = formatInfo.FormattedHeader.InnerHeight;
return new Rectangle(left, top, width, height);
}
Rectangle GetFooterRect()
{
Area contentArea = _renderInfo.LayoutInfo.ContentArea;
ChartFormatInfo formatInfo = (ChartFormatInfo)_renderInfo.FormatInfo;
XUnit left = contentArea.X;
XUnit top = contentArea.Y + contentArea.Height - formatInfo.FormattedFooter.InnerHeight;
XUnit width = contentArea.Width;
XUnit height = formatInfo.FormattedFooter.InnerHeight;
return new Rectangle(left, top, width, height);
}
Rectangle GetTopRect()
{
Area contentArea = _renderInfo.LayoutInfo.ContentArea;
ChartFormatInfo formatInfo = (ChartFormatInfo)_renderInfo.FormatInfo;
XUnit left;
XUnit right;
GetTopBottomHorizontalPosition(out left, out right);
XUnit top = contentArea.Y;
if (formatInfo.FormattedHeader != null)
top += formatInfo.FormattedHeader.InnerHeight;
XUnit height = formatInfo.FormattedTop.InnerHeight;
return new Rectangle(left, top, right - left, height);
}
Rectangle GetBottomRect()
{
Area contentArea = _renderInfo.LayoutInfo.ContentArea;
ChartFormatInfo formatInfo = (ChartFormatInfo)_renderInfo.FormatInfo;
XUnit left;
XUnit right;
GetTopBottomHorizontalPosition(out left, out right);
XUnit top = contentArea.Y + contentArea.Height - formatInfo.FormattedBottom.InnerHeight;
if (formatInfo.FormattedFooter != null)
top -= formatInfo.FormattedFooter.InnerHeight;
XUnit height = formatInfo.FormattedBottom.InnerHeight;
return new Rectangle(left, top, right - left, height);
}
Rectangle GetPlotRect()
{
Area contentArea = _renderInfo.LayoutInfo.ContentArea;
ChartFormatInfo formatInfo = (ChartFormatInfo)_renderInfo.FormatInfo;
XUnit top = contentArea.Y;
if (formatInfo.FormattedHeader != null)
top += formatInfo.FormattedHeader.InnerHeight;
if (formatInfo.FormattedTop != null)
top += formatInfo.FormattedTop.InnerHeight;
XUnit bottom = contentArea.Y + contentArea.Height;
if (formatInfo.FormattedFooter != null)
bottom -= formatInfo.FormattedFooter.InnerHeight;
if (formatInfo.FormattedBottom != null)
bottom -= formatInfo.FormattedBottom.InnerHeight;
XUnit left = contentArea.X;
if (formatInfo.FormattedLeft != null)
left += formatInfo.FormattedLeft.InnerWidth;
XUnit right = contentArea.X + contentArea.Width;
if (formatInfo.FormattedRight != null)
right -= formatInfo.FormattedRight.InnerWidth;
return new Rectangle(left, top, right - left, bottom - top);
}
public override void Format(Area area, FormatInfo previousFormatInfo)
{
ChartFormatInfo formatInfo = (ChartFormatInfo)_renderInfo.FormatInfo;
TextArea textArea = (TextArea)_chart.GetValue("HeaderArea", GV.ReadOnly);
formatInfo.FormattedHeader = GetFormattedTextArea(textArea, _chart.Width.Point);
textArea = (TextArea)_chart.GetValue("FooterArea", GV.ReadOnly);
formatInfo.FormattedFooter = GetFormattedTextArea(textArea, _chart.Width.Point);
textArea = (TextArea)_chart.GetValue("LeftArea", GV.ReadOnly);
formatInfo.FormattedLeft = GetFormattedTextArea(textArea);
textArea = (TextArea)_chart.GetValue("RightArea", GV.ReadOnly);
formatInfo.FormattedRight = GetFormattedTextArea(textArea);
textArea = (TextArea)_chart.GetValue("TopArea", GV.ReadOnly);
formatInfo.FormattedTop = GetFormattedTextArea(textArea, GetTopBottomWidth());
textArea = (TextArea)_chart.GetValue("BottomArea", GV.ReadOnly);
formatInfo.FormattedBottom = GetFormattedTextArea(textArea, GetTopBottomWidth());
base.Format(area, previousFormatInfo);
formatInfo.ChartFrame = ChartMapper.ChartMapper.Map(_chart);
}
XUnit AlignVertically(VerticalAlignment vAlign, XUnit top, XUnit bottom, XUnit height)
{
switch (vAlign)
{
case VerticalAlignment.Bottom:
return bottom - height;
case VerticalAlignment.Center:
return (top + bottom - height) / 2;
default:
return top;
}
}
/// <summary>
/// Gets the width of the top and bottom area.
/// Used while formatting.
/// </summary>
/// <returns>The width of the top and bottom area</returns>
private XUnit GetTopBottomWidth()
{
ChartFormatInfo formatInfo = (ChartFormatInfo)_renderInfo.FormatInfo;
XUnit width = _chart.Width.Point;
if (formatInfo.FormattedRight != null)
width -= formatInfo.FormattedRight.InnerWidth;
if (formatInfo.FormattedLeft != null)
width -= formatInfo.FormattedLeft.InnerWidth;
return width;
}
/// <summary>
/// Gets the horizontal boundaries of the top and bottom area.
/// Used while rendering.
/// </summary>
/// <param name="left">The left boundary of the top and bottom area</param>
/// <param name="right">The right boundary of the top and bottom area</param>
private void GetTopBottomHorizontalPosition(out XUnit left, out XUnit right)
{
Area contentArea = _renderInfo.LayoutInfo.ContentArea;
ChartFormatInfo formatInfo = (ChartFormatInfo)_renderInfo.FormatInfo;
left = contentArea.X;
right = contentArea.X + contentArea.Width;
if (formatInfo.FormattedRight != null)
right -= formatInfo.FormattedRight.InnerWidth;
if (formatInfo.FormattedLeft != null)
left += formatInfo.FormattedLeft.InnerWidth;
}
void RenderArea(FormattedTextArea area, Rectangle rect)
{
if (area == null)
return;
TextArea textArea = area.TextArea;
FillFormatRenderer fillFormatRenderer = new FillFormatRenderer((FillFormat)textArea.GetValue("FillFormat", GV.ReadOnly), _gfx);
fillFormatRenderer.Render(rect.X, rect.Y, rect.Width, rect.Height);
XUnit top = rect.Y;
top += textArea.TopPadding;
XUnit bottom = rect.Y + rect.Height;
bottom -= textArea.BottomPadding;
top = AlignVertically(textArea.VerticalAlignment, top, bottom, area.ContentHeight);
XUnit left = rect.X;
left += textArea.LeftPadding;
RenderInfo[] renderInfos = area.GetRenderInfos();
RenderByInfos(left, top, renderInfos);
LineFormatRenderer lineFormatRenderer = new LineFormatRenderer((LineFormat)textArea.GetValue("LineFormat", GV.ReadOnly), _gfx);
lineFormatRenderer.Render(rect.X, rect.Y, rect.Width, rect.Height);
}
public override void Render()
{
RenderFilling();
Area contentArea = _renderInfo.LayoutInfo.ContentArea;
ChartFormatInfo formatInfo = (ChartFormatInfo)_renderInfo.FormatInfo;
if (formatInfo.FormattedHeader != null)
RenderArea(formatInfo.FormattedHeader, GetHeaderRect());
if (formatInfo.FormattedFooter != null)
RenderArea(formatInfo.FormattedFooter, GetFooterRect());
if (formatInfo.FormattedTop != null)
RenderArea(formatInfo.FormattedTop, GetTopRect());
if (formatInfo.FormattedBottom != null)
RenderArea(formatInfo.FormattedBottom, GetBottomRect());
if (formatInfo.FormattedLeft != null)
RenderArea(formatInfo.FormattedLeft, GetLeftRect());
if (formatInfo.FormattedRight != null)
RenderArea(formatInfo.FormattedRight, GetRightRect());
PlotArea plotArea = (PlotArea)_chart.GetValue("PlotArea", GV.ReadOnly);
if (plotArea != null)
RenderPlotArea(plotArea, GetPlotRect());
RenderLine();
}
void RenderPlotArea(PlotArea area, Rectangle rect)
{
PdfSharp.Charting.ChartFrame chartFrame = ((ChartFormatInfo)_renderInfo.FormatInfo).ChartFrame;
XUnit top = rect.Y;
top += area.TopPadding;
XUnit bottom = rect.Y + rect.Height;
bottom -= area.BottomPadding;
XUnit left = rect.X;
left += area.LeftPadding;
XUnit right = rect.X + rect.Width;
right -= area.RightPadding;
chartFrame.Location = new XPoint(left, top);
chartFrame.Size = new XSize(right - left, bottom - top);
chartFrame.DrawChart(_gfx);
}
readonly Chart _chart;
}
}