#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 { /// /// Renders a chart to an XGraphics object. /// 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; } } /// /// Gets the width of the top and bottom area. /// Used while formatting. /// /// The width of the top and bottom area 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; } /// /// Gets the horizontal boundaries of the top and bottom area. /// Used while rendering. /// /// The left boundary of the top and bottom area /// The right boundary of the top and bottom area 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; } }