This commit is contained in:
2021-05-25 17:00:45 +05:00
parent e2fcfed44c
commit ec2dac13d8
1172 changed files with 5636 additions and 5839 deletions

View File

@@ -0,0 +1,189 @@
#region PDFsharp Charting - A .NET charting library based on PDFsharp
//
// Authors:
// Niklas Schneider
//
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.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 PdfSharp.Drawing;
namespace PdfSharp.Charting.Renderers
{
/// <summary>
/// Represents an area chart renderer.
/// </summary>
internal class AreaChartRenderer : ColumnLikeChartRenderer
{
/// <summary>
/// Initializes a new instance of the AreaChartRenderer class with the
/// specified renderer parameters.
/// </summary>
internal AreaChartRenderer(RendererParameters parms)
: base(parms)
{ }
/// <summary>
/// Returns an initialized and renderer specific rendererInfo.
/// </summary>
internal override RendererInfo Init()
{
ChartRendererInfo cri = new ChartRendererInfo();
cri._chart = (Chart)_rendererParms.DrawingItem;
_rendererParms.RendererInfo = cri;
InitSeriesRendererInfo();
LegendRenderer lr = new ColumnLikeLegendRenderer(_rendererParms);
cri.legendRendererInfo = (LegendRendererInfo)lr.Init();
AxisRenderer xar = new HorizontalXAxisRenderer(_rendererParms);
cri.xAxisRendererInfo = (AxisRendererInfo)xar.Init();
AxisRenderer yar = new VerticalYAxisRenderer(_rendererParms);
cri.yAxisRendererInfo = (AxisRendererInfo)yar.Init();
PlotArea plotArea = cri._chart.PlotArea;
PlotAreaRenderer renderer = new AreaPlotAreaRenderer(_rendererParms);
cri.plotAreaRendererInfo = (PlotAreaRendererInfo)renderer.Init();
return cri;
}
/// <summary>
/// Layouts and calculates the space used by the line chart.
/// </summary>
internal override void Format()
{
ChartRendererInfo cri = (ChartRendererInfo)_rendererParms.RendererInfo;
LegendRenderer lr = new ColumnLikeLegendRenderer(_rendererParms);
lr.Format();
// axes
AxisRenderer xar = new HorizontalXAxisRenderer(_rendererParms);
xar.Format();
AxisRenderer yar = new VerticalYAxisRenderer(_rendererParms);
yar.Format();
// Calculate rects and positions.
CalcLayout();
// Calculated remaining plot area, now it's safe to format.
PlotAreaRenderer renderer = new AreaPlotAreaRenderer(_rendererParms);
renderer.Format();
}
/// <summary>
/// Draws the column chart.
/// </summary>
internal override void Draw()
{
ChartRendererInfo cri = (ChartRendererInfo)_rendererParms.RendererInfo;
LegendRenderer lr = new ColumnLikeLegendRenderer(_rendererParms);
lr.Draw();
// Draw wall.
WallRenderer wr = new WallRenderer(_rendererParms);
wr.Draw();
// Draw gridlines.
GridlinesRenderer glr = new ColumnLikeGridlinesRenderer(_rendererParms);
glr.Draw();
PlotAreaBorderRenderer pabr = new PlotAreaBorderRenderer(_rendererParms);
pabr.Draw();
PlotAreaRenderer renderer = new AreaPlotAreaRenderer(_rendererParms);
renderer.Draw();
// Draw axes.
if (cri.xAxisRendererInfo._axis != null)
{
AxisRenderer xar = new HorizontalXAxisRenderer(_rendererParms);
xar.Draw();
}
if (cri.yAxisRendererInfo._axis != null)
{
AxisRenderer yar = new VerticalYAxisRenderer(_rendererParms);
yar.Draw();
}
}
/// <summary>
/// Initializes all necessary data to draw a series for an area chart.
/// </summary>
private void InitSeriesRendererInfo()
{
ChartRendererInfo cri = (ChartRendererInfo)_rendererParms.RendererInfo;
SeriesCollection seriesColl = cri._chart.SeriesCollection;
cri.seriesRendererInfos = new SeriesRendererInfo[seriesColl.Count];
for (int idx = 0; idx < seriesColl.Count; ++idx)
{
SeriesRendererInfo sri = new SeriesRendererInfo();
sri._series = seriesColl[idx];
cri.seriesRendererInfos[idx] = sri;
}
InitSeries();
}
/// <summary>
/// Initializes all necessary data to draw a series for an area chart.
/// </summary>
internal void InitSeries()
{
ChartRendererInfo cri = (ChartRendererInfo)_rendererParms.RendererInfo;
int seriesIndex = 0;
foreach (SeriesRendererInfo sri in cri.seriesRendererInfos)
{
sri.LineFormat = Converter.ToXPen(sri._series._lineFormat, XColors.Black, ChartRenderer.DefaultSeriesLineWidth);
sri.FillFormat = Converter.ToXBrush(sri._series._fillFormat, ColumnColors.Item(seriesIndex++));
sri._pointRendererInfos = new PointRendererInfo[sri._series._seriesElements.Count];
for (int pointIdx = 0; pointIdx < sri._pointRendererInfos.Length; ++pointIdx)
{
PointRendererInfo pri = new PointRendererInfo();
Point point = sri._series._seriesElements[pointIdx];
pri.Point = point;
if (point != null)
{
pri.LineFormat = sri.LineFormat;
pri.FillFormat = sri.FillFormat;
if (point._lineFormat != null && !point._lineFormat._color.IsEmpty)
pri.LineFormat = new XPen(point._lineFormat._color, point._lineFormat._width);
if (point._fillFormat != null && !point._lineFormat._color.IsEmpty)
pri.FillFormat = new XSolidBrush(point._fillFormat._color);
}
sri._pointRendererInfos[pointIdx] = pri;
}
}
}
}
}

View File

@@ -0,0 +1,85 @@
#region PDFsharp Charting - A .NET charting library based on PDFsharp
//
// Authors:
// Niklas Schneider
//
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.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 PdfSharp.Drawing;
namespace PdfSharp.Charting.Renderers
{
/// <summary>
/// Represents a plot area renderer of areas.
/// </summary>
internal class AreaPlotAreaRenderer : ColumnLikePlotAreaRenderer
{
/// <summary>
/// Initializes a new instance of the AreaPlotAreaRenderer class
/// with the specified renderer parameters.
/// </summary>
internal AreaPlotAreaRenderer(RendererParameters parms)
: base(parms)
{ }
/// <summary>
/// Draws the content of the area plot area.
/// </summary>
internal override void Draw()
{
ChartRendererInfo cri = (ChartRendererInfo)_rendererParms.RendererInfo;
XRect plotAreaRect = cri.plotAreaRendererInfo.Rect;
if (plotAreaRect.IsEmpty)
return;
XGraphics gfx = _rendererParms.Graphics;
XGraphicsState state = gfx.Save();
//gfx.SetClip(plotAreaRect, XCombineMode.Intersect);
gfx.IntersectClip(plotAreaRect);
XMatrix matrix = cri.plotAreaRendererInfo._matrix;
double xMajorTick = cri.xAxisRendererInfo.MajorTick;
foreach (SeriesRendererInfo sri in cri.seriesRendererInfos)
{
int count = sri._series.Elements.Count;
XPoint[] points = new XPoint[count + 2];
points[0] = new XPoint(xMajorTick / 2, 0);
for (int idx = 0; idx < count; idx++)
{
double pointValue = sri._series.Elements[idx].Value;
if (double.IsNaN(pointValue))
pointValue = 0;
points[idx + 1] = new XPoint(idx + xMajorTick / 2, pointValue);
}
points[count + 1] = new XPoint(count - 1 + xMajorTick / 2, 0);
matrix.TransformPoints(points);
gfx.DrawPolygon(sri.LineFormat, sri.FillFormat, points, XFillMode.Winding);
}
//gfx.ResetClip();
gfx.Restore(state);
}
}
}

View File

@@ -0,0 +1,189 @@
#region PDFsharp Charting - A .NET charting library based on PDFsharp
//
// Authors:
// Niklas Schneider
//
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.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 PdfSharp.Drawing;
namespace PdfSharp.Charting.Renderers
{
/// <summary>
/// Represents the base for all specialized axis renderer. Initialization common too all
/// axis renderer should come here.
/// </summary>
internal abstract class AxisRenderer : Renderer
{
/// <summary>
/// Initializes a new instance of the AxisRenderer class with the specified renderer parameters.
/// </summary>
internal AxisRenderer(RendererParameters parms)
: base(parms)
{ }
/// <summary>
/// Initializes the axis title of the rendererInfo. All missing font attributes will be taken
/// from the specified defaultFont.
/// </summary>
protected void InitAxisTitle(AxisRendererInfo rendererInfo, XFont defaultFont)
{
if (rendererInfo._axis._title != null)
{
AxisTitleRendererInfo atri = new AxisTitleRendererInfo();
rendererInfo._axisTitleRendererInfo = atri;
atri._axisTitle = rendererInfo._axis._title;
atri.AxisTitleText = rendererInfo._axis._title._caption;
atri.AxisTitleAlignment = rendererInfo._axis._title._alignment;
atri.AxisTitleVerticalAlignment = rendererInfo._axis._title._verticalAlignment;
atri.AxisTitleFont = Converter.ToXFont(rendererInfo._axis._title._font, defaultFont);
XColor fontColor = XColors.Black;
if (rendererInfo._axis._title._font != null && !rendererInfo._axis._title._font._color.IsEmpty)
fontColor = rendererInfo._axis._title._font._color;
atri.AxisTitleBrush = new XSolidBrush(fontColor);
atri.AxisTitleOrientation = rendererInfo._axis._title._orientation;
}
}
/// <summary>
/// Initializes the tick labels of the rendererInfo. All missing font attributes will be taken
/// from the specified defaultFont.
/// </summary>
protected void InitTickLabels(AxisRendererInfo rendererInfo, XFont defaultFont)
{
if (rendererInfo._axis._tickLabels != null)
{
rendererInfo.TickLabelsFont = Converter.ToXFont(rendererInfo._axis._tickLabels._font, defaultFont);
XColor fontColor = XColors.Black;
if (rendererInfo._axis._tickLabels._font != null && !rendererInfo._axis._tickLabels._font._color.IsEmpty)
fontColor = rendererInfo._axis._tickLabels._font._color;
rendererInfo.TickLabelsBrush = new XSolidBrush(fontColor);
rendererInfo.TickLabelsFormat = rendererInfo._axis._tickLabels._format;
if (rendererInfo.TickLabelsFormat == null)
rendererInfo.TickLabelsFormat = GetDefaultTickLabelsFormat();
}
else
{
rendererInfo.TickLabelsFont = defaultFont;
rendererInfo.TickLabelsBrush = new XSolidBrush(XColors.Black);
rendererInfo.TickLabelsFormat = GetDefaultTickLabelsFormat();
}
}
/// <summary>
/// Initializes the line format of the rendererInfo.
/// </summary>
protected void InitAxisLineFormat(AxisRendererInfo rendererInfo)
{
if (rendererInfo._axis._minorTickMarkInitialized)
rendererInfo.MinorTickMark = rendererInfo._axis.MinorTickMark;
if (rendererInfo._axis._majorTickMarkInitialized)
rendererInfo.MajorTickMark = rendererInfo._axis.MajorTickMark;
else
rendererInfo.MajorTickMark = TickMarkType.Outside;
if (rendererInfo.MinorTickMark != TickMarkType.None)
rendererInfo.MinorTickMarkLineFormat = Converter.ToXPen(rendererInfo._axis._lineFormat, XColors.Black, DefaultMinorTickMarkLineWidth);
if (rendererInfo.MajorTickMark != TickMarkType.None)
rendererInfo.MajorTickMarkLineFormat = Converter.ToXPen(rendererInfo._axis._lineFormat, XColors.Black, DefaultMajorTickMarkLineWidth);
if (rendererInfo._axis._lineFormat != null)
{
rendererInfo.LineFormat = Converter.ToXPen(rendererInfo._axis.LineFormat, XColors.Black, DefaultLineWidth);
if (!rendererInfo._axis._majorTickMarkInitialized)
rendererInfo.MajorTickMark = TickMarkType.Outside;
}
}
/// <summary>
/// Initializes the gridlines of the rendererInfo.
/// </summary>
protected void InitGridlines(AxisRendererInfo rendererInfo)
{
if (rendererInfo._axis._minorGridlines != null)
{
rendererInfo.MinorGridlinesLineFormat =
Converter.ToXPen(rendererInfo._axis._minorGridlines._lineFormat, XColors.Black, DefaultGridLineWidth);
}
else if (rendererInfo._axis._hasMinorGridlines)
{
// No minor gridlines object are given, but user asked for.
rendererInfo.MinorGridlinesLineFormat = new XPen(XColors.Black, DefaultGridLineWidth);
}
if (rendererInfo._axis._majorGridlines != null)
{
rendererInfo.MajorGridlinesLineFormat =
Converter.ToXPen(rendererInfo._axis._majorGridlines._lineFormat, XColors.Black, DefaultGridLineWidth);
}
else if (rendererInfo._axis._hasMajorGridlines)
{
// No major gridlines object are given, but user asked for.
rendererInfo.MajorGridlinesLineFormat = new XPen(XColors.Black, DefaultGridLineWidth);
}
}
/// <summary>
/// Default width for a variety of lines.
/// </summary>
protected const double DefaultLineWidth = 0.4; // 0.15 mm
/// <summary>
/// Default width for a gridlines.
/// </summary>
protected const double DefaultGridLineWidth = 0.15;
/// <summary>
/// Default width for major tick marks.
/// </summary>
protected const double DefaultMajorTickMarkLineWidth = 1;
/// <summary>
/// Default width for minor tick marks.
/// </summary>
protected const double DefaultMinorTickMarkLineWidth = 1;
/// <summary>
/// Default width of major tick marks.
/// </summary>
protected const double DefaultMajorTickMarkWidth = 4.3; // 1.5 mm
/// <summary>
/// Default width of minor tick marks.
/// </summary>
protected const double DefaultMinorTickMarkWidth = 2.8; // 1 mm
/// <summary>
/// Default width of space between label and tick mark.
/// </summary>
protected const double SpaceBetweenLabelAndTickmark = 2.1; // 0.7 mm
protected abstract string GetDefaultTickLabelsFormat();
}
}

View File

@@ -0,0 +1,182 @@
#region PDFsharp Charting - A .NET charting library based on PDFsharp
//
// Authors:
// Niklas Schneider
//
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.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 System;
using PdfSharp.Drawing;
namespace PdfSharp.Charting.Renderers
{
/// <summary>
/// Represents a axis title renderer used for x and y axis titles.
/// </summary>
internal class AxisTitleRenderer : Renderer
{
/// <summary>
/// Initializes a new instance of the AxisTitleRenderer class with the
/// specified renderer parameters.
/// </summary>
internal AxisTitleRenderer(RendererParameters parms)
: base(parms)
{ }
/// <summary>
/// Calculates the space used for the axis title.
/// </summary>
internal override void Format()
{
XGraphics gfx = _rendererParms.Graphics;
AxisTitleRendererInfo atri = ((AxisRendererInfo)_rendererParms.RendererInfo)._axisTitleRendererInfo;
if (atri.AxisTitleText != "")
{
XSize size = gfx.MeasureString(atri.AxisTitleText, atri.AxisTitleFont);
if (atri.AxisTitleOrientation != 0)
{
XPoint[] points = new XPoint[2];
points[0].X = 0;
points[0].Y = 0;
points[1].X = size.Width;
points[1].Y = size.Height;
XMatrix matrix = new XMatrix();
matrix.RotatePrepend(-atri.AxisTitleOrientation);
matrix.TransformPoints(points);
size.Width = Math.Abs(points[1].X - points[0].X);
size.Height = Math.Abs(points[1].Y - points[0].Y);
}
atri.X = 0;
atri.Y = 0;
atri.Height = size.Height;
atri.Width = size.Width;
}
}
/// <summary>
/// Draws the axis title.
/// </summary>
internal override void Draw()
{
AxisRendererInfo ari = (AxisRendererInfo)_rendererParms.RendererInfo;
AxisTitleRendererInfo atri = ari._axisTitleRendererInfo;
if (atri.AxisTitleText != "")
{
XGraphics gfx = _rendererParms.Graphics;
if (atri.AxisTitleOrientation != 0)
{
XRect layout = atri.Rect;
layout.X = -(layout.Width / 2);
layout.Y = -(layout.Height / 2);
double x = 0;
switch (atri.AxisTitleAlignment)
{
case HorizontalAlignment.Center:
x = atri.X + atri.Width / 2;
break;
case HorizontalAlignment.Right:
x = atri.X + atri.Width - layout.Width / 2;
break;
case HorizontalAlignment.Left:
default:
x = atri.X;
break;
}
double y = 0;
switch (atri.AxisTitleVerticalAlignment)
{
case VerticalAlignment.Center:
y = atri.Y + atri.Height / 2;
break;
case VerticalAlignment.Bottom:
y = atri.Y + atri.Height - layout.Height / 2;
break;
case VerticalAlignment.Top:
default:
y = atri.Y;
break;
}
XStringFormat xsf = new XStringFormat();
xsf.Alignment = XStringAlignment.Center;
xsf.LineAlignment = XLineAlignment.Center;
XGraphicsState state = gfx.Save();
gfx.TranslateTransform(x, y);
gfx.RotateTransform(-atri.AxisTitleOrientation);
gfx.DrawString(atri.AxisTitleText, atri.AxisTitleFont, atri.AxisTitleBrush, layout, xsf);
gfx.Restore(state);
}
else
{
XStringFormat format = new XStringFormat();
switch (atri.AxisTitleAlignment)
{
case HorizontalAlignment.Center:
format.Alignment = XStringAlignment.Center;
break;
case HorizontalAlignment.Right:
format.Alignment = XStringAlignment.Far;
break;
case HorizontalAlignment.Left:
default:
format.Alignment = XStringAlignment.Near;
break;
}
switch (atri.AxisTitleVerticalAlignment)
{
case VerticalAlignment.Center:
format.LineAlignment = XLineAlignment.Center;
break;
case VerticalAlignment.Bottom:
format.LineAlignment = XLineAlignment.Far;
break;
case VerticalAlignment.Top:
default:
format.LineAlignment = XLineAlignment.Near;
break;
}
gfx.DrawString(atri.AxisTitleText, atri.AxisTitleFont, atri.AxisTitleBrush, atri.Rect, format);
}
}
}
}
}

View File

@@ -0,0 +1,257 @@
#region PDFsharp Charting - A .NET charting library based on PDFsharp
//
// Authors:
// Niklas Schneider
//
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.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 PdfSharp.Drawing;
namespace PdfSharp.Charting.Renderers
{
/// <summary>
/// Represents a bar chart renderer.
/// </summary>
internal class BarChartRenderer : ChartRenderer
{
/// <summary>
/// Initializes a new instance of the BarChartRenderer class with the
/// specified renderer parameters.
/// </summary>
internal BarChartRenderer(RendererParameters parms)
: base(parms)
{ }
/// <summary>
/// Returns an initialized and renderer specific rendererInfo.
/// </summary>
internal override RendererInfo Init()
{
ChartRendererInfo cri = new ChartRendererInfo();
cri._chart = (Chart)_rendererParms.DrawingItem;
_rendererParms.RendererInfo = cri;
InitSeriesRendererInfo();
LegendRenderer lr = GetLegendRenderer();
cri.legendRendererInfo = (LegendRendererInfo)lr.Init();
AxisRenderer xar = new VerticalXAxisRenderer(_rendererParms);
cri.xAxisRendererInfo = (AxisRendererInfo)xar.Init();
AxisRenderer yar = GetYAxisRenderer();
cri.yAxisRendererInfo = (AxisRendererInfo)yar.Init();
PlotArea plotArea = cri._chart.PlotArea;
PlotAreaRenderer renderer = GetPlotAreaRenderer();
cri.plotAreaRendererInfo = (PlotAreaRendererInfo)renderer.Init();
DataLabelRenderer dlr = new BarDataLabelRenderer(_rendererParms);
dlr.Init();
return cri;
}
/// <summary>
/// Layouts and calculates the space used by the column chart.
/// </summary>
internal override void Format()
{
ChartRendererInfo cri = (ChartRendererInfo)_rendererParms.RendererInfo;
LegendRenderer lr = GetLegendRenderer();
lr.Format();
// axes
AxisRenderer xar = new VerticalXAxisRenderer(_rendererParms);
xar.Format();
AxisRenderer yar = GetYAxisRenderer();
yar.Format();
// Calculate rects and positions.
XRect chartRect = LayoutLegend();
cri.xAxisRendererInfo.X = chartRect.Left;
cri.xAxisRendererInfo.Y = chartRect.Top;
cri.xAxisRendererInfo.Height = chartRect.Height - cri.yAxisRendererInfo.Height;
cri.yAxisRendererInfo.X = chartRect.Left + cri.xAxisRendererInfo.Width;
cri.yAxisRendererInfo.Y = chartRect.Bottom - cri.yAxisRendererInfo.Height;
cri.yAxisRendererInfo.Width = chartRect.Width - cri.xAxisRendererInfo.Width;
cri.plotAreaRendererInfo.X = cri.yAxisRendererInfo.X;
cri.plotAreaRendererInfo.Y = cri.xAxisRendererInfo.Y;
cri.plotAreaRendererInfo.Width = cri.yAxisRendererInfo.InnerRect.Width;
cri.plotAreaRendererInfo.Height = cri.xAxisRendererInfo.Height;
// Calculated remaining plot area, now it's safe to format.
PlotAreaRenderer renderer = GetPlotAreaRenderer();
renderer.Format();
DataLabelRenderer dlr = new BarDataLabelRenderer(_rendererParms);
dlr.Format();
}
/// <summary>
/// Draws the column chart.
/// </summary>
internal override void Draw()
{
ChartRendererInfo cri = (ChartRendererInfo)_rendererParms.RendererInfo;
LegendRenderer lr = GetLegendRenderer();
lr.Draw();
WallRenderer wr = new WallRenderer(_rendererParms);
wr.Draw();
GridlinesRenderer glr = new BarGridlinesRenderer(_rendererParms);
glr.Draw();
PlotAreaBorderRenderer pabr = new PlotAreaBorderRenderer(_rendererParms);
pabr.Draw();
PlotAreaRenderer renderer = GetPlotAreaRenderer();
renderer.Draw();
DataLabelRenderer dlr = new BarDataLabelRenderer(_rendererParms);
dlr.Draw();
if (cri.xAxisRendererInfo._axis != null)
{
AxisRenderer xar = new VerticalXAxisRenderer(_rendererParms);
xar.Draw();
}
if (cri.yAxisRendererInfo._axis != null)
{
AxisRenderer yar = GetYAxisRenderer();
yar.Draw();
}
}
/// <summary>
/// Returns the specific plot area renderer.
/// </summary>
private PlotAreaRenderer GetPlotAreaRenderer()
{
Chart chart = (Chart)_rendererParms.DrawingItem;
switch (chart._type)
{
case ChartType.Bar2D:
return new BarClusteredPlotAreaRenderer(_rendererParms);
case ChartType.BarStacked2D:
return new BarStackedPlotAreaRenderer(_rendererParms);
}
return null;
}
/// <summary>
/// Returns the specific legend renderer.
/// </summary>
private LegendRenderer GetLegendRenderer()
{
Chart chart = (Chart)_rendererParms.DrawingItem;
switch (chart._type)
{
case ChartType.Bar2D:
return new BarClusteredLegendRenderer(_rendererParms);
case ChartType.BarStacked2D:
return new ColumnLikeLegendRenderer(_rendererParms);
}
return null;
}
/// <summary>
/// Returns the specific plot area renderer.
/// </summary>
private YAxisRenderer GetYAxisRenderer()
{
Chart chart = (Chart)_rendererParms.DrawingItem;
switch (chart._type)
{
case ChartType.Bar2D:
return new HorizontalYAxisRenderer(_rendererParms);
case ChartType.BarStacked2D:
return new HorizontalStackedYAxisRenderer(_rendererParms);
}
return null;
}
/// <summary>
/// Initializes all necessary data to draw all series for a column chart.
/// </summary>
private void InitSeriesRendererInfo()
{
ChartRendererInfo cri = (ChartRendererInfo)_rendererParms.RendererInfo;
SeriesCollection seriesColl = cri._chart.SeriesCollection;
cri.seriesRendererInfos = new SeriesRendererInfo[seriesColl.Count];
// Lowest series is the first, like in Excel
for (int idx = 0; idx < seriesColl.Count; ++idx)
{
SeriesRendererInfo sri = new SeriesRendererInfo();
sri._series = seriesColl[idx];
cri.seriesRendererInfos[idx] = sri;
}
InitSeries();
}
/// <summary>
/// Initializes all necessary data to draw all series for a column chart.
/// </summary>
internal void InitSeries()
{
ChartRendererInfo cri = (ChartRendererInfo)_rendererParms.RendererInfo;
int seriesIndex = 0;
foreach (SeriesRendererInfo sri in cri.seriesRendererInfos)
{
sri.LineFormat = Converter.ToXPen(sri._series._lineFormat, XColors.Black, DefaultSeriesLineWidth);
sri.FillFormat = Converter.ToXBrush(sri._series._fillFormat, ColumnColors.Item(seriesIndex++));
sri._pointRendererInfos = new ColumnRendererInfo[sri._series._seriesElements.Count];
for (int pointIdx = 0; pointIdx < sri._pointRendererInfos.Length; ++pointIdx)
{
PointRendererInfo pri = new ColumnRendererInfo();
Point point = sri._series._seriesElements[pointIdx];
pri.Point = point;
if (point != null)
{
pri.LineFormat = sri.LineFormat;
pri.FillFormat = sri.FillFormat;
if (point._lineFormat != null && !point._lineFormat._color.IsEmpty)
pri.LineFormat = Converter.ToXPen(point._lineFormat, sri.LineFormat);
if (point._fillFormat != null && !point._fillFormat._color.IsEmpty)
pri.FillFormat = new XSolidBrush(point._fillFormat._color);
}
sri._pointRendererInfos[pointIdx] = pri;
}
}
}
}
}

View File

@@ -0,0 +1,105 @@
#region PDFsharp Charting - A .NET charting library based on PDFsharp
//
// Authors:
// Niklas Schneider
//
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.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 PdfSharp.Drawing;
namespace PdfSharp.Charting.Renderers
{
/// <summary>
/// Represents the legend renderer specific to bar charts.
/// </summary>
internal class BarClusteredLegendRenderer : ColumnLikeLegendRenderer
{
/// <summary>
/// Initializes a new instance of the BarClusteredLegendRenderer class with the
/// specified renderer parameters.
/// </summary>
internal BarClusteredLegendRenderer(RendererParameters parms)
: base(parms)
{ }
/// <summary>
/// Draws the legend.
/// </summary>
internal override void Draw()
{
ChartRendererInfo cri = (ChartRendererInfo)_rendererParms.RendererInfo;
LegendRendererInfo lri = cri.legendRendererInfo;
if (lri == null)
return;
XGraphics gfx = _rendererParms.Graphics;
RendererParameters parms = new RendererParameters();
parms.Graphics = gfx;
LegendEntryRenderer ler = new LegendEntryRenderer(parms);
bool verticalLegend = (lri._legend._docking == DockingType.Left || lri._legend._docking == DockingType.Right);
int paddingFactor = 1;
if (lri.BorderPen != null)
paddingFactor = 2;
XRect legendRect = lri.Rect;
legendRect.X += LeftPadding * paddingFactor;
if (verticalLegend)
legendRect.Y = legendRect.Bottom - BottomPadding * paddingFactor;
else
legendRect.Y += TopPadding * paddingFactor;
foreach (LegendEntryRendererInfo leri in cri.legendRendererInfo.Entries)
{
if (verticalLegend)
legendRect.Y -= leri.Height;
XRect entryRect = legendRect;
entryRect.Width = leri.Width;
entryRect.Height = leri.Height;
leri.Rect = entryRect;
parms.RendererInfo = leri;
ler.Draw();
if (verticalLegend)
legendRect.Y -= EntrySpacing;
else
legendRect.X += entryRect.Width + EntrySpacing;
}
// Draw border around legend
if (lri.BorderPen != null)
{
XRect borderRect = lri.Rect;
borderRect.X += LeftPadding;
borderRect.Y += TopPadding;
borderRect.Width -= LeftPadding + RightPadding;
borderRect.Height -= TopPadding + BottomPadding;
gfx.DrawRectangle(lri.BorderPen, borderRect);
}
}
}
}

View File

@@ -0,0 +1,127 @@
#region PDFsharp Charting - A .NET charting library based on PDFsharp
//
// Authors:
// Niklas Schneider
//
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.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 PdfSharp.Drawing;
namespace PdfSharp.Charting.Renderers
{
/// <summary>
/// Represents a plot area renderer of clustered bars, i. e. all bars are drawn side by side.
/// </summary>
internal class BarClusteredPlotAreaRenderer : BarPlotAreaRenderer
{
/// <summary>
/// Initializes a new instance of the BarClusteredPlotAreaRenderer class with the
/// specified renderer parameters.
/// </summary>
internal BarClusteredPlotAreaRenderer(RendererParameters parms)
: base(parms)
{ }
/// <summary>
/// Calculates the position, width and height of each bar of all series.
/// </summary>
protected override void CalcBars()
{
ChartRendererInfo cri = (ChartRendererInfo)_rendererParms.RendererInfo;
if (cri.seriesRendererInfos.Length == 0)
return;
double xMax = cri.xAxisRendererInfo.MaximumScale;
double yMin = cri.yAxisRendererInfo.MinimumScale;
double yMax = cri.yAxisRendererInfo.MaximumScale;
int pointCount = 0;
foreach (SeriesRendererInfo sri in cri.seriesRendererInfos)
pointCount += sri._series._seriesElements.Count;
// Space shared by one clustered bar.
double groupWidth = cri.xAxisRendererInfo.MajorTick;
// Space used by one bar.
double columnWidth = groupWidth * 0.75 / cri.seriesRendererInfos.Length;
int seriesIdx = 0;
XPoint[] points = new XPoint[2];
foreach (SeriesRendererInfo sri in cri.seriesRendererInfos)
{
// Set x to first clustered bar for each series.
double x = xMax - groupWidth / 2;
// Offset for bars of a particular series from the start of a clustered bar.
double dx = (columnWidth * seriesIdx) - (columnWidth / 2 * cri.seriesRendererInfos.Length);
double y0 = yMin;
foreach (ColumnRendererInfo column in sri._pointRendererInfos)
{
if (column.Point != null)
{
double x0 = x - dx;
double x1 = x - dx - columnWidth;
double y1 = column.Point.Value;
// Draw from zero base line, if it exists.
if (y0 < 0 && yMax >= 0)
y0 = 0;
// y0 should always be lower than y1, i. e. draw bar from bottom to top.
if (y1 < 0 && y1 < y0)
{
double y = y0;
y0 = y1;
y1 = y;
}
points[0].X = y0; // upper left
points[0].Y = x0;
points[1].X = y1; // lower right
points[1].Y = x1;
cri.plotAreaRendererInfo._matrix.TransformPoints(points);
column.Rect = new XRect(points[0].X,
points[1].Y,
points[1].X - points[0].X,
points[0].Y - points[1].Y);
}
x--; // Next clustered bar.
}
seriesIdx++;
}
}
/// <summary>
/// If yValue is within the range from yMin to yMax returns true, otherwise false.
/// </summary>
protected override bool IsDataInside(double yMin, double yMax, double yValue)
{
return yValue <= yMax && yValue >= yMin;
}
}
}

View File

@@ -0,0 +1,162 @@
#region PDFsharp Charting - A .NET charting library based on PDFsharp
//
// Authors:
// Niklas Schneider
//
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.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 System;
using PdfSharp.Drawing;
namespace PdfSharp.Charting.Renderers
{
/// <summary>
/// Represents a data label renderer for bar charts.
/// </summary>
internal class BarDataLabelRenderer : DataLabelRenderer
{
/// <summary>
/// Initializes a new instance of the BarDataLabelRenderer class with the
/// specified renderer parameters.
/// </summary>
internal BarDataLabelRenderer(RendererParameters parms)
: base(parms)
{ }
/// <summary>
/// Calculates the space used by the data labels.
/// </summary>
internal override void Format()
{
ChartRendererInfo cri = (ChartRendererInfo)_rendererParms.RendererInfo;
foreach (SeriesRendererInfo sri in cri.seriesRendererInfos)
{
if (sri._dataLabelRendererInfo == null)
continue;
XGraphics gfx = _rendererParms.Graphics;
sri._dataLabelRendererInfo.Entries = new DataLabelEntryRendererInfo[sri._pointRendererInfos.Length];
int index = 0;
foreach (ColumnRendererInfo column in sri._pointRendererInfos)
{
DataLabelEntryRendererInfo dleri = new DataLabelEntryRendererInfo();
if (sri._dataLabelRendererInfo.Type != DataLabelType.None)
{
if (sri._dataLabelRendererInfo.Type == DataLabelType.Value)
dleri.Text = column.Point._value.ToString(sri._dataLabelRendererInfo.Format);
else if (sri._dataLabelRendererInfo.Type == DataLabelType.Percent)
throw new InvalidOperationException(PSCSR.PercentNotSupportedByColumnDataLabel);
if (dleri.Text.Length > 0)
dleri.Size = gfx.MeasureString(dleri.Text, sri._dataLabelRendererInfo.Font);
}
sri._dataLabelRendererInfo.Entries[index++] = dleri;
}
}
CalcPositions();
}
/// <summary>
/// Draws the data labels of the bar chart.
/// </summary>
internal override void Draw()
{
ChartRendererInfo cri = (ChartRendererInfo)_rendererParms.RendererInfo;
foreach (SeriesRendererInfo sri in cri.seriesRendererInfos)
{
if (sri._dataLabelRendererInfo == null)
continue;
XGraphics gfx = _rendererParms.Graphics;
XFont font = sri._dataLabelRendererInfo.Font;
XBrush fontColor = sri._dataLabelRendererInfo.FontColor;
XStringFormat format = XStringFormats.Center;
format.LineAlignment = XLineAlignment.Center;
foreach (DataLabelEntryRendererInfo dataLabel in sri._dataLabelRendererInfo.Entries)
{
if (dataLabel.Text != null)
gfx.DrawString(dataLabel.Text, font, fontColor, dataLabel.Rect, format);
}
}
}
/// <summary>
/// Calculates the data label positions specific for column charts.
/// </summary>
internal override void CalcPositions()
{
ChartRendererInfo cri = (ChartRendererInfo)_rendererParms.RendererInfo;
XGraphics gfx = _rendererParms.Graphics;
foreach (SeriesRendererInfo sri in cri.seriesRendererInfos)
{
if (sri._dataLabelRendererInfo == null)
continue;
int columnIndex = 0;
foreach (ColumnRendererInfo bar in sri._pointRendererInfos)
{
DataLabelEntryRendererInfo dleri = sri._dataLabelRendererInfo.Entries[columnIndex++];
dleri.Y = bar.Rect.Y + (bar.Rect.Height - dleri.Height) / 2; // Always the same...
switch (sri._dataLabelRendererInfo.Position)
{
case DataLabelPosition.InsideEnd:
// Inner border of the column.
dleri.X = bar.Rect.X;
if (bar.Point._value > 0)
dleri.X += bar.Rect.Width - dleri.Width;
break;
case DataLabelPosition.Center:
// Centered inside the column.
dleri.X = bar.Rect.X + (bar.Rect.Width - dleri.Width) / 2;
break;
case DataLabelPosition.InsideBase:
// Aligned at the base of the column.
dleri.X = bar.Rect.X;
if (bar.Point._value < 0)
dleri.X += bar.Rect.Width - dleri.Width;
break;
case DataLabelPosition.OutsideEnd:
// Outer border of the column.
dleri.X = bar.Rect.X;
if (bar.Point._value > 0)
dleri.X += bar.Rect.Width;
else
dleri.X -= dleri.Width;
break;
}
}
}
}
}
}

View File

@@ -0,0 +1,135 @@
#region PDFsharp Charting - A .NET charting library based on PDFsharp
//
// Authors:
// Niklas Schneider
//
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.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 PdfSharp.Drawing;
namespace PdfSharp.Charting.Renderers
{
/// <summary>
/// Represents gridlines used by bar charts, i. e. X axis grid will be rendered
/// from left to right and Y axis grid will be rendered from top to bottom of the plot area.
/// </summary>
internal class BarGridlinesRenderer : GridlinesRenderer
{
/// <summary>
/// Initializes a new instance of the BarGridlinesRenderer class with the
/// specified renderer parameters.
/// </summary>
internal BarGridlinesRenderer(RendererParameters parms)
: base(parms)
{ }
/// <summary>
/// Draws the gridlines into the plot area.
/// </summary>
internal override void Draw()
{
ChartRendererInfo cri = (ChartRendererInfo)_rendererParms.RendererInfo;
XRect plotAreaRect = cri.plotAreaRendererInfo.Rect;
if (plotAreaRect.IsEmpty)
return;
AxisRendererInfo xari = cri.xAxisRendererInfo;
AxisRendererInfo yari = cri.yAxisRendererInfo;
double xMin = xari.MinimumScale;
double xMax = xari.MaximumScale;
double yMin = yari.MinimumScale;
double yMax = yari.MaximumScale;
double xMajorTick = xari.MajorTick;
double yMajorTick = yari.MajorTick;
double xMinorTick = xari.MinorTick;
double yMinorTick = yari.MinorTick;
double xMaxExtension = xari.MajorTick;
XMatrix matrix = cri.plotAreaRendererInfo._matrix;
LineFormatRenderer lineFormatRenderer;
XGraphics gfx = _rendererParms.Graphics;
XPoint[] points = new XPoint[2];
if (xari.MinorGridlinesLineFormat != null)
{
lineFormatRenderer = new LineFormatRenderer(gfx, xari.MinorGridlinesLineFormat);
for (double x = xMin + xMinorTick; x < xMax; x += xMinorTick)
{
points[0].Y = x;
points[0].X = yMin;
points[1].Y = x;
points[1].X = yMax;
matrix.TransformPoints(points);
lineFormatRenderer.DrawLine(points[0], points[1]);
}
}
if (xari.MajorGridlinesLineFormat != null)
{
lineFormatRenderer = new LineFormatRenderer(gfx, xari.MajorGridlinesLineFormat);
for (double x = xMin; x <= xMax; x += xMajorTick)
{
points[0].Y = x;
points[0].X = yMin;
points[1].Y = x;
points[1].X = yMax;
matrix.TransformPoints(points);
lineFormatRenderer.DrawLine(points[0], points[1]);
}
}
if (yari.MinorGridlinesLineFormat != null)
{
lineFormatRenderer = new LineFormatRenderer(gfx, yari.MinorGridlinesLineFormat);
for (double y = yMin + yMinorTick; y < yMax; y += yMinorTick)
{
points[0].Y = xMin;
points[0].X = y;
points[1].Y = xMax;
points[1].X = y;
matrix.TransformPoints(points);
lineFormatRenderer.DrawLine(points[0], points[1]);
}
}
if (yari.MajorGridlinesLineFormat != null)
{
lineFormatRenderer = new LineFormatRenderer(gfx, yari.MajorGridlinesLineFormat);
for (double y = yMin; y <= yMax; y += yMajorTick)
{
points[0].Y = xMin;
points[0].X = y;
points[1].Y = xMax;
points[1].X = y;
matrix.TransformPoints(points);
lineFormatRenderer.DrawLine(points[0], points[1]);
}
}
}
}
}

View File

@@ -0,0 +1,154 @@
#region PDFsharp Charting - A .NET charting library based on PDFsharp
//
// Authors:
// Niklas Schneider
//
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.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 PdfSharp.Drawing;
namespace PdfSharp.Charting.Renderers
{
/// <summary>
/// Represents a plot area renderer for bars.
/// </summary>
internal abstract class BarPlotAreaRenderer : PlotAreaRenderer
{
/// <summary>
/// Initializes a new instance of the BarPlotAreaRenderer class with the
/// specified renderer parameters.
/// </summary>
internal BarPlotAreaRenderer(RendererParameters parms)
: base(parms)
{ }
/// <summary>
/// Layouts and calculates the space for each bar.
/// </summary>
internal override void Format()
{
ChartRendererInfo cri = (ChartRendererInfo)_rendererParms.RendererInfo;
double xMin = cri.xAxisRendererInfo.MinimumScale;
double xMax = cri.xAxisRendererInfo.MaximumScale;
double yMin = cri.yAxisRendererInfo.MinimumScale;
double yMax = cri.yAxisRendererInfo.MaximumScale;
double xMajorTick = cri.xAxisRendererInfo.MajorTick;
XRect plotAreaBox = cri.plotAreaRendererInfo.Rect;
cri.plotAreaRendererInfo._matrix = new XMatrix();
cri.plotAreaRendererInfo._matrix.TranslatePrepend(-yMin, xMin);
cri.plotAreaRendererInfo._matrix.Scale(plotAreaBox.Width / (yMax - yMin), plotAreaBox.Height / (xMax - xMin), XMatrixOrder.Append);
cri.plotAreaRendererInfo._matrix.Translate(plotAreaBox.X, plotAreaBox.Y, XMatrixOrder.Append);
CalcBars();
}
/// <summary>
/// Draws the content of the bar plot area.
/// </summary>
internal override void Draw()
{
ChartRendererInfo cri = (ChartRendererInfo)_rendererParms.RendererInfo;
XRect plotAreaBox = cri.plotAreaRendererInfo.Rect;
if (plotAreaBox.IsEmpty)
return;
XGraphics gfx = _rendererParms.Graphics;
double xMin = cri.xAxisRendererInfo.MinimumScale;
double xMax = cri.xAxisRendererInfo.MaximumScale;
double yMin = cri.yAxisRendererInfo.MinimumScale;
double yMax = cri.yAxisRendererInfo.MaximumScale;
double xMajorTick = cri.xAxisRendererInfo.MajorTick;
LineFormatRenderer lineFormatRenderer;
// Under some circumstances it is possible that no zero base line will be drawn,
// e. g. because of unfavourable minimum/maximum scale and/or major tick, so force to draw
// a zero base line if necessary.
if (cri.yAxisRendererInfo.MajorGridlinesLineFormat != null ||
cri.yAxisRendererInfo.MinorGridlinesLineFormat != null)
{
if (yMin < 0 && yMax > 0)
{
XPoint[] points = new XPoint[2];
points[0].X = 0;
points[0].Y = xMin;
points[1].X = 0;
points[1].Y = xMax;
cri.plotAreaRendererInfo._matrix.TransformPoints(points);
if (cri.yAxisRendererInfo.MinorGridlinesLineFormat != null)
lineFormatRenderer = new LineFormatRenderer(gfx, cri.yAxisRendererInfo.MinorGridlinesLineFormat);
else
lineFormatRenderer = new LineFormatRenderer(gfx, cri.yAxisRendererInfo.MajorGridlinesLineFormat);
lineFormatRenderer.DrawLine(points[0], points[1]);
}
}
// Draw bars
XGraphicsState state = gfx.Save();
foreach (SeriesRendererInfo sri in cri.seriesRendererInfos)
{
foreach (ColumnRendererInfo column in sri._pointRendererInfos)
{
// Do not draw bar if value is outside yMin/yMax range. Clipping does not make sense.
if (IsDataInside(yMin, yMax, column.Point._value))
gfx.DrawRectangle(column.FillFormat, column.Rect);
}
}
// Draw borders around bar.
// A border can overlap neighbor bars, so it is important to draw borders at the end.
foreach (SeriesRendererInfo sri in cri.seriesRendererInfos)
{
foreach (ColumnRendererInfo column in sri._pointRendererInfos)
{
// Do not draw bar if value is outside yMin/yMax range. Clipping does not make sense.
if (IsDataInside(yMin, yMax, column.Point._value))
{
lineFormatRenderer = new LineFormatRenderer(gfx, column.LineFormat);
lineFormatRenderer.DrawRectangle(column.Rect);
}
}
}
gfx.Restore(state);
}
/// <summary>
/// Calculates the position, width and height of each bar of all series.
/// </summary>
protected abstract void CalcBars();
/// <summary>
/// If yValue is within the range from yMin to yMax returns true, otherwise false.
/// </summary>
protected abstract bool IsDataInside(double yMin, double yMax, double yValue);
}
}

View File

@@ -0,0 +1,122 @@
#region PDFsharp Charting - A .NET charting library based on PDFsharp
//
// Authors:
// Niklas Schneider
//
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.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 System;
using PdfSharp.Drawing;
namespace PdfSharp.Charting.Renderers
{
/// <summary>
/// Represents a plot area renderer of stacked bars, i. e. all bars are drawn one on another.
/// </summary>
internal class BarStackedPlotAreaRenderer : BarPlotAreaRenderer
{
/// <summary>
/// Initializes a new instance of the BarStackedPlotAreaRenderer class with the
/// specified renderer parameters.
/// </summary>
internal BarStackedPlotAreaRenderer(RendererParameters parms)
: base(parms)
{ }
/// <summary>
/// Calculates the position, width and height of each bar of all series.
/// </summary>
protected override void CalcBars()
{
ChartRendererInfo cri = (ChartRendererInfo)_rendererParms.RendererInfo;
if (cri.seriesRendererInfos.Length == 0)
return;
double xMax = cri.xAxisRendererInfo.MaximumScale;
double xMajorTick = cri.xAxisRendererInfo.MajorTick;
int maxPoints = 0;
foreach (SeriesRendererInfo sri in cri.seriesRendererInfos)
maxPoints = Math.Max(maxPoints, sri._series._seriesElements.Count);
// Space used by one bar.
double x = xMax - xMajorTick / 2;
double columnWidth = xMajorTick * 0.75 / 2;
XPoint[] points = new XPoint[2];
for (int pointIdx = 0; pointIdx < maxPoints; ++pointIdx)
{
double yMin = 0, yMax = 0, y0 = 0, y1 = 0;
double x0 = x - columnWidth;
double x1 = x + columnWidth;
foreach (SeriesRendererInfo sri in cri.seriesRendererInfos)
{
if (sri._pointRendererInfos.Length <= pointIdx)
break;
ColumnRendererInfo column = (ColumnRendererInfo)sri._pointRendererInfos[pointIdx];
if (column.Point != null && !double.IsNaN(column.Point._value))
{
double y = column.Point._value;
if (y < 0)
{
y0 = yMin + y;
y1 = yMin;
yMin += y;
}
else
{
y0 = yMax;
y1 = yMax + y;
yMax += y;
}
points[0].Y = x0; // oben links
points[0].X = y0;
points[1].Y = x1; // unten rechts
points[1].X = y1;
cri.plotAreaRendererInfo._matrix.TransformPoints(points);
column.Rect = new XRect(points[0].X,
points[0].Y,
points[1].X - points[0].X,
points[1].Y - points[0].Y);
}
}
x--; // Next stacked column.
}
}
/// <summary>
/// If yValue is within the range from yMin to yMax returns true, otherwise false.
/// </summary>
protected override bool IsDataInside(double yMin, double yMax, double yValue)
{
return yValue <= yMax && yValue >= yMin;
}
}
}

View File

@@ -0,0 +1,100 @@
#region PDFsharp Charting - A .NET charting library based on PDFsharp
//
// Authors:
// Niklas Schneider
//
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.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 PdfSharp.Drawing;
namespace PdfSharp.Charting.Renderers
{
/// <summary>
/// Represents the base class for all chart renderers.
/// </summary>
internal abstract class ChartRenderer : Renderer
{
/// <summary>
/// Initializes a new instance of the ChartRenderer class with the specified renderer parameters.
/// </summary>
internal ChartRenderer(RendererParameters parms)
: base(parms)
{ }
/// <summary>
/// Calculates the space used by the legend and returns the remaining space available for the
/// other parts of the chart.
/// </summary>
protected XRect LayoutLegend()
{
ChartRendererInfo cri = (ChartRendererInfo)_rendererParms.RendererInfo;
XRect remainingRect = _rendererParms.Box;
if (cri.legendRendererInfo != null)
{
switch (cri.legendRendererInfo._legend.Docking)
{
case DockingType.Left:
cri.legendRendererInfo.X = remainingRect.Left;
cri.legendRendererInfo.Y = remainingRect.Height / 2 - cri.legendRendererInfo.Height / 2;
double width = cri.legendRendererInfo.Width + LegendSpacing;
remainingRect.X += width;
remainingRect.Width -= width;
break;
case DockingType.Right:
cri.legendRendererInfo.X = remainingRect.Right - cri.legendRendererInfo.Width;
cri.legendRendererInfo.Y = remainingRect.Height / 2 - cri.legendRendererInfo.Height / 2;
remainingRect.Width -= cri.legendRendererInfo.Width + LegendSpacing;
break;
case DockingType.Top:
cri.legendRendererInfo.X = remainingRect.Width / 2 - cri.legendRendererInfo.Width / 2;
cri.legendRendererInfo.Y = remainingRect.Top;
double height = cri.legendRendererInfo.Height + LegendSpacing;
remainingRect.Y += height;
remainingRect.Height -= height;
break;
case DockingType.Bottom:
cri.legendRendererInfo.X = remainingRect.Width / 2 - cri.legendRendererInfo.Width / 2;
cri.legendRendererInfo.Y = remainingRect.Bottom - cri.legendRendererInfo.Height;
remainingRect.Height -= cri.legendRendererInfo.Height + LegendSpacing;
break;
}
}
return remainingRect;
}
/// <summary>
/// Used to separate the legend from the plot area.
/// </summary>
private const double LegendSpacing = 0;
/// <summary>
/// Represents the default width for all series lines, like borders in column/bar charts.
/// </summary>
protected static readonly double DefaultSeriesLineWidth = 0.15;
}
}

View File

@@ -0,0 +1,126 @@
#region PDFsharp Charting - A .NET charting library based on PDFsharp
//
// Authors:
// Niklas Schneider
//
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.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 PdfSharp.Drawing;
namespace PdfSharp.Charting.Renderers
{
/// <summary>
/// Represents the predefined column/bar chart colors.
/// </summary>
internal sealed class ColumnColors
{
/// <summary>
/// Gets the color for column/bar charts from the specified index.
/// </summary>
public static XColor Item(int index)
{
return XColor.FromArgb((int)_seriesColors[index]);
}
/// <summary>
/// Colors for column/bar charts taken from Excel.
/// </summary>
static readonly uint[] _seriesColors = new uint[]
{
0xFF9999FF, 0xFF993366, 0xFFFFFFCC, 0xFFCCFFFF, 0xFF660066, 0xFFFF8080,
0xFF0066CC, 0xFFCCCCFF, 0xFF000080, 0xFFFF00FF, 0xFFFFFF00, 0xFF00FFFF,
0xFF800080, 0xFF800000, 0xFF008080, 0xFF0000FF, 0xFF00CCFF, 0xFFCCFFFF,
0xFFCCFFCC, 0xFFFFFF99, 0xFF99CCFF, 0xFFFF99CC, 0xFFCC99FF, 0xFFFFCC99,
0xFF3366FF, 0xFF33CCCC, 0xFF99CC00, 0xFFFFCC00, 0xFFFF9900, 0xFFFF6600,
0xFF666699, 0xFF969696, 0xFF003366, 0xFF339966, 0xFF003300, 0xFF333300,
0xFF993300, 0xFF993366, 0xFF333399, 0xFF333333, 0xFF000000, 0xFFFFFFFF,
0xFFFF0000, 0xFF00FF00, 0xFF0000FF, 0xFFFFFF00, 0xFFFF00FF, 0xFF00FFFF,
0xFF800000, 0xFF008000, 0xFF000080, 0xFF808000, 0xFF800080, 0xFF008080,
0xFFC0C0C0, 0xFF808080
};
}
/// <summary>
/// Represents the predefined line chart colors.
/// </summary>
internal sealed class LineColors
{
/// <summary>
/// Gets the color for line charts from the specified index.
/// </summary>
public static XColor Item(int index)
{
return XColor.FromArgb((int)_lineColors[index]);
}
/// <summary>
/// Colors for line charts taken from Excel.
/// </summary>
static readonly uint[] _lineColors = new uint[]
{
0xFF000080, 0xFFFF00FF, 0xFFFFFF00, 0xFF00FFFF, 0xFF800080, 0xFF800000,
0xFF008080, 0xFF0000FF, 0xFF00CCFF, 0xFFCCFFFF, 0xFFCCFFCC, 0xFFFFFF99,
0xFF99CCFF, 0xFFFF99CC, 0xFFCC99FF, 0xFFFFCC99, 0xFF3366FF, 0xFF33CCCC,
0xFF99CC00, 0xFFFFCC00, 0xFFFF9900, 0xFFFF6600, 0xFF666699, 0xFF969696,
0xFF003366, 0xFF339966, 0xFF003300, 0xFF333300, 0xFF993300, 0xFF993366,
0xFF333399, 0xFF000000, 0xFFFFFFFF, 0xFFFF0000, 0xFF00FF00, 0xFF0000FF,
0xFFFFFF00, 0xFFFF00FF, 0xFF00FFFF, 0xFF800000, 0xFF008000, 0xFF000080,
0xFF808000, 0xFF800080, 0xFF008080, 0xFFC0C0C0, 0xFF808080, 0xFF9999FF,
0xFF993366, 0xFFFFFFCC, 0xFFCCFFFF, 0xFF660066, 0xFFFF8080, 0xFF0066CC,
0xFFCCCCFF
};
}
/// <summary>
/// Represents the predefined pie chart colors.
/// </summary>
internal sealed class PieColors
{
/// <summary>
/// Gets the color for pie charts from the specified index.
/// </summary>
public static XColor Item(int index)
{
return XColor.FromArgb((int)_sectorColors[index]);
}
/// <summary>
/// Colors for pie charts taken from Excel.
/// </summary>
static readonly uint[] _sectorColors = new uint[]
{
0xFF9999FF, 0xFF993366, 0xFFFFFFCC, 0xFFCCFFFF, 0xFF660066, 0xFFFF8080,
0xFF0066CC, 0xFFCCCCFF, 0xFF000080, 0xFFFF00FF, 0xFFFFFF00, 0xFF00FFFF,
0xFF800080, 0xFF800000, 0xFF008080, 0xFF0000FF, 0xFF00CCFF, 0xFFCCFFFF,
0xFFCCFFCC, 0xFFFFFF99, 0xFF99CCFF, 0xFFFF99CC, 0xFFCC99FF, 0xFFFFCC99,
0xFF3366FF, 0xFF33CCCC, 0xFF99CC00, 0xFFFFCC00, 0xFFFF9900, 0xFFFF6600,
0xFF666699, 0xFF969696, 0xFF003366, 0xFF339966, 0xFF003300, 0xFF333300,
0xFF993300, 0xFF993366, 0xFF333399, 0xFF333333, 0xFF000000, 0xFFFFFFFF,
0xFFFF0000, 0xFF00FF00, 0xFF0000FF, 0xFFFFFF00, 0xFFFF00FF, 0xFF00FFFF,
0xFF800000, 0xFF008000, 0xFF000080, 0xFF808000, 0xFF800080, 0xFF008080,
0xFFC0C0C0, 0xFF808080
};
}
}

View File

@@ -0,0 +1,229 @@
#region PDFsharp Charting - A .NET charting library based on PDFsharp
//
// Authors:
// Niklas Schneider
//
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.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 PdfSharp.Drawing;
namespace PdfSharp.Charting.Renderers
{
/// <summary>
/// Represents a column chart renderer.
/// </summary>
internal class ColumnChartRenderer : ColumnLikeChartRenderer
{
/// <summary>
/// Initializes a new instance of the ColumnChartRenderer class with the
/// specified renderer parameters.
/// </summary>
internal ColumnChartRenderer(RendererParameters parms)
: base(parms)
{ }
/// <summary>
/// Returns an initialized and renderer specific rendererInfo.
/// </summary>
internal override RendererInfo Init()
{
ChartRendererInfo cri = new ChartRendererInfo();
cri._chart = (Chart)_rendererParms.DrawingItem;
_rendererParms.RendererInfo = cri;
InitSeriesRendererInfo();
LegendRenderer lr = new ColumnLikeLegendRenderer(_rendererParms);
cri.legendRendererInfo = (LegendRendererInfo)lr.Init();
AxisRenderer xar = new HorizontalXAxisRenderer(_rendererParms);
cri.xAxisRendererInfo = (AxisRendererInfo)xar.Init();
AxisRenderer yar = GetYAxisRenderer();
cri.yAxisRendererInfo = (AxisRendererInfo)yar.Init();
PlotArea plotArea = cri._chart.PlotArea;
PlotAreaRenderer renderer = GetPlotAreaRenderer();
cri.plotAreaRendererInfo = (PlotAreaRendererInfo)renderer.Init();
DataLabelRenderer dlr = new ColumnDataLabelRenderer(_rendererParms);
dlr.Init();
return cri;
}
/// <summary>
/// Layouts and calculates the space used by the column chart.
/// </summary>
internal override void Format()
{
ChartRendererInfo cri = (ChartRendererInfo)_rendererParms.RendererInfo;
LegendRenderer lr = new ColumnLikeLegendRenderer(_rendererParms);
lr.Format();
// axes
AxisRenderer xar = new HorizontalXAxisRenderer(_rendererParms);
xar.Format();
AxisRenderer yar = GetYAxisRenderer();
yar.Format();
// Calculate rects and positions.
CalcLayout();
// Calculated remaining plot area, now it's safe to format.
PlotAreaRenderer renderer = GetPlotAreaRenderer();
renderer.Format();
DataLabelRenderer dlr = new ColumnDataLabelRenderer(_rendererParms);
dlr.Format();
}
/// <summary>
/// Draws the column chart.
/// </summary>
internal override void Draw()
{
ChartRendererInfo cri = (ChartRendererInfo)_rendererParms.RendererInfo;
LegendRenderer lr = new ColumnLikeLegendRenderer(_rendererParms);
lr.Draw();
WallRenderer wr = new WallRenderer(_rendererParms);
wr.Draw();
GridlinesRenderer glr = new ColumnLikeGridlinesRenderer(_rendererParms);
glr.Draw();
PlotAreaBorderRenderer pabr = new PlotAreaBorderRenderer(_rendererParms);
pabr.Draw();
PlotAreaRenderer renderer = GetPlotAreaRenderer();
renderer.Draw();
DataLabelRenderer dlr = new ColumnDataLabelRenderer(_rendererParms);
dlr.Draw();
if (cri.xAxisRendererInfo._axis != null)
{
AxisRenderer xar = new HorizontalXAxisRenderer(_rendererParms);
xar.Draw();
}
if (cri.yAxisRendererInfo._axis != null)
{
AxisRenderer yar = GetYAxisRenderer();
yar.Draw();
}
}
/// <summary>
/// Returns the specific plot area renderer.
/// </summary>
private PlotAreaRenderer GetPlotAreaRenderer()
{
Chart chart = (Chart)_rendererParms.DrawingItem;
switch (chart._type)
{
case ChartType.Column2D:
return new ColumnClusteredPlotAreaRenderer(_rendererParms);
case ChartType.ColumnStacked2D:
return new ColumnStackedPlotAreaRenderer(_rendererParms);
}
return null;
}
/// <summary>
/// Returns the specific y axis renderer.
/// </summary>
private YAxisRenderer GetYAxisRenderer()
{
Chart chart = (Chart)_rendererParms.DrawingItem;
switch (chart._type)
{
case ChartType.Column2D:
return new VerticalYAxisRenderer(_rendererParms);
case ChartType.ColumnStacked2D:
return new VerticalStackedYAxisRenderer(_rendererParms);
}
return null;
}
/// <summary>
/// Initializes all necessary data to draw all series for a column chart.
/// </summary>
private void InitSeriesRendererInfo()
{
ChartRendererInfo cri = (ChartRendererInfo)_rendererParms.RendererInfo;
SeriesCollection seriesColl = cri._chart.SeriesCollection;
cri.seriesRendererInfos = new SeriesRendererInfo[seriesColl.Count];
for (int idx = 0; idx < seriesColl.Count; ++idx)
{
SeriesRendererInfo sri = new SeriesRendererInfo();
sri._series = seriesColl[idx];
cri.seriesRendererInfos[idx] = sri;
}
InitSeries();
}
/// <summary>
/// Initializes all necessary data to draw all series for a column chart.
/// </summary>
internal void InitSeries()
{
ChartRendererInfo cri = (ChartRendererInfo)_rendererParms.RendererInfo;
int seriesIndex = 0;
foreach (SeriesRendererInfo sri in cri.seriesRendererInfos)
{
sri.LineFormat = Converter.ToXPen(sri._series._lineFormat, XColors.Black, ChartRenderer.DefaultSeriesLineWidth);
sri.FillFormat = Converter.ToXBrush(sri._series._fillFormat, ColumnColors.Item(seriesIndex++));
sri._pointRendererInfos = new ColumnRendererInfo[sri._series._seriesElements.Count];
for (int pointIdx = 0; pointIdx < sri._pointRendererInfos.Length; ++pointIdx)
{
PointRendererInfo pri = new ColumnRendererInfo();
Point point = sri._series._seriesElements[pointIdx];
pri.Point = point;
if (point != null)
{
pri.LineFormat = sri.LineFormat;
pri.FillFormat = sri.FillFormat;
if (point._lineFormat != null)
pri.LineFormat = Converter.ToXPen(point._lineFormat, sri.LineFormat);
if (point._fillFormat != null && !point._fillFormat._color.IsEmpty)
pri.FillFormat = new XSolidBrush(point._fillFormat._color);
}
sri._pointRendererInfos[pointIdx] = pri;
}
}
}
}
}

View File

@@ -0,0 +1,127 @@
#region PDFsharp Charting - A .NET charting library based on PDFsharp
//
// Authors:
// Niklas Schneider
//
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.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 PdfSharp.Drawing;
namespace PdfSharp.Charting.Renderers
{
/// <summary>
/// Represents a plot area renderer of clustered columns, i. e. all columns are drawn side by side.
/// </summary>
internal class ColumnClusteredPlotAreaRenderer : ColumnPlotAreaRenderer
{
/// <summary>
/// Initializes a new instance of the ColumnClusteredPlotAreaRenderer class with the
/// specified renderer parameters.
/// </summary>
internal ColumnClusteredPlotAreaRenderer(RendererParameters parms)
: base(parms)
{ }
/// <summary>
/// Calculates the position, width and height of each column of all series.
/// </summary>
protected override void CalcColumns()
{
ChartRendererInfo cri = (ChartRendererInfo)_rendererParms.RendererInfo;
if (cri.seriesRendererInfos.Length == 0)
return;
double xMin = cri.xAxisRendererInfo.MinimumScale;
double yMin = cri.yAxisRendererInfo.MinimumScale;
double yMax = cri.yAxisRendererInfo.MaximumScale;
int pointCount = 0;
foreach (SeriesRendererInfo sr in cri.seriesRendererInfos)
pointCount += sr._series._seriesElements.Count;
// Space shared by one clustered column.
double groupWidth = cri.xAxisRendererInfo.MajorTick;
// Space used by one column.
double columnWidth = groupWidth * 3 / 4 / cri.seriesRendererInfos.Length;
int seriesIdx = 0;
XPoint[] points = new XPoint[2];
foreach (SeriesRendererInfo sri in cri.seriesRendererInfos)
{
// Set x to first clustered column for each series.
double x = xMin + groupWidth / 2;
// Offset for columns of a particular series from the start of a clustered cloumn.
double dx = (columnWidth * seriesIdx) - (columnWidth / 2 * cri.seriesRendererInfos.Length);
foreach (ColumnRendererInfo column in sri._pointRendererInfos)
{
if (column.Point != null)
{
double x0 = x + dx;
double x1 = x + dx + columnWidth;
double y0 = yMin;
double y1 = column.Point.Value;
// Draw from zero base line, if it exists.
if (y0 < 0 && yMax >= 0)
y0 = 0;
// y0 should always be lower than y1, i. e. draw column from bottom to top.
if (y1 < 0 && y1 < y0)
{
double y = y0;
y0 = y1;
y1 = y;
}
points[0].X = x0; // upper left
points[0].Y = y1;
points[1].X = x1; // lower right
points[1].Y = y0;
cri.plotAreaRendererInfo._matrix.TransformPoints(points);
column.Rect = new XRect(points[0].X,
points[0].Y,
points[1].X - points[0].X,
points[1].Y - points[0].Y);
}
x++; // Next clustered column.
}
seriesIdx++;
}
}
/// <summary>
/// If yValue is within the range from yMin to yMax returns true, otherwise false.
/// </summary>
protected override bool IsDataInside(double yMin, double yMax, double yValue)
{
return yValue <= yMax && yValue >= yMin;
}
}
}

View File

@@ -0,0 +1,160 @@
#region PDFsharp Charting - A .NET charting library based on PDFsharp
//
// Authors:
// Niklas Schneider
//
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.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 System;
using PdfSharp.Drawing;
namespace PdfSharp.Charting.Renderers
{
/// <summary>
/// Represents a data label renderer for column charts.
/// </summary>
internal class ColumnDataLabelRenderer : DataLabelRenderer
{
/// <summary>
/// Initializes a new instance of the ColumnDataLabelRenderer class with the
/// specified renderer parameters.
/// </summary>
internal ColumnDataLabelRenderer(RendererParameters parms)
: base(parms)
{ }
/// <summary>
/// Calculates the space used by the data labels.
/// </summary>
internal override void Format()
{
ChartRendererInfo cri = (ChartRendererInfo)_rendererParms.RendererInfo;
foreach (SeriesRendererInfo sri in cri.seriesRendererInfos)
{
if (sri._dataLabelRendererInfo == null)
continue;
XGraphics gfx = _rendererParms.Graphics;
sri._dataLabelRendererInfo.Entries = new DataLabelEntryRendererInfo[sri._pointRendererInfos.Length];
int index = 0;
foreach (ColumnRendererInfo column in sri._pointRendererInfos)
{
DataLabelEntryRendererInfo dleri = new DataLabelEntryRendererInfo();
if (sri._dataLabelRendererInfo.Type != DataLabelType.None)
{
if (sri._dataLabelRendererInfo.Type == DataLabelType.Value)
dleri.Text = column.Point._value.ToString(sri._dataLabelRendererInfo.Format);
else if (sri._dataLabelRendererInfo.Type == DataLabelType.Percent)
throw new InvalidOperationException(PSCSR.PercentNotSupportedByColumnDataLabel);
if (dleri.Text.Length > 0)
dleri.Size = gfx.MeasureString(dleri.Text, sri._dataLabelRendererInfo.Font);
}
sri._dataLabelRendererInfo.Entries[index++] = dleri;
}
}
CalcPositions();
}
/// <summary>
/// Draws the data labels of the column chart.
/// </summary>
internal override void Draw()
{
ChartRendererInfo cri = (ChartRendererInfo)_rendererParms.RendererInfo;
foreach (SeriesRendererInfo sri in cri.seriesRendererInfos)
{
if (sri._dataLabelRendererInfo == null)
continue;
XGraphics gfx = _rendererParms.Graphics;
XFont font = sri._dataLabelRendererInfo.Font;
XBrush fontColor = sri._dataLabelRendererInfo.FontColor;
XStringFormat format = XStringFormats.Center;
format.LineAlignment = XLineAlignment.Center;
foreach (DataLabelEntryRendererInfo dataLabel in sri._dataLabelRendererInfo.Entries)
{
if (dataLabel.Text != null)
gfx.DrawString(dataLabel.Text, font, fontColor, dataLabel.Rect, format);
}
}
}
/// <summary>
/// Calculates the data label positions specific for column charts.
/// </summary>
internal override void CalcPositions()
{
ChartRendererInfo cri = (ChartRendererInfo)_rendererParms.RendererInfo;
XGraphics gfx = _rendererParms.Graphics;
foreach (SeriesRendererInfo sri in cri.seriesRendererInfos)
{
if (sri._dataLabelRendererInfo == null)
continue;
int columnIndex = 0;
foreach (ColumnRendererInfo column in sri._pointRendererInfos)
{
DataLabelEntryRendererInfo dleri = sri._dataLabelRendererInfo.Entries[columnIndex++];
dleri.X = column.Rect.X + column.Rect.Width / 2 - dleri.Width / 2; // Always the same...
switch (sri._dataLabelRendererInfo.Position)
{
case DataLabelPosition.InsideEnd:
// Inner border of the column.
dleri.Y = column.Rect.Y;
if (column.Point._value < 0)
dleri.Y = column.Rect.Y + column.Rect.Height - dleri.Height;
break;
case DataLabelPosition.Center:
// Centered inside the column.
dleri.Y = column.Rect.Y + column.Rect.Height / 2 - dleri.Height / 2;
break;
case DataLabelPosition.InsideBase:
// Aligned at the base of the column.
dleri.Y = column.Rect.Y + column.Rect.Height - dleri.Height;
if (column.Point._value < 0)
dleri.Y = column.Rect.Y;
break;
case DataLabelPosition.OutsideEnd:
// Outer border of the column.
dleri.Y = column.Rect.Y - dleri.Height;
if (column.Point._value < 0)
dleri.Y = column.Rect.Y + column.Rect.Height;
break;
}
}
}
}
}
}

View File

@@ -0,0 +1,68 @@
#region PDFsharp Charting - A .NET charting library based on PDFsharp
//
// Authors:
// Niklas Schneider
//
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.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 PdfSharp.Drawing;
namespace PdfSharp.Charting.Renderers
{
/// <summary>
/// Represents column like chart renderer.
/// </summary>
internal abstract class ColumnLikeChartRenderer : ChartRenderer
{
/// <summary>
/// Initializes a new instance of the ColumnLikeChartRenderer class with the
/// specified renderer parameters.
/// </summary>
internal ColumnLikeChartRenderer(RendererParameters parms)
: base(parms)
{ }
/// <summary>
/// Calculates the chart layout.
/// </summary>
internal void CalcLayout()
{
ChartRendererInfo cri = (ChartRendererInfo)_rendererParms.RendererInfo;
// Calculate rects and positions.
XRect chartRect = LayoutLegend();
cri.xAxisRendererInfo.X = chartRect.Left + cri.yAxisRendererInfo.Width;
cri.xAxisRendererInfo.Y = chartRect.Bottom - cri.xAxisRendererInfo.Height;
cri.xAxisRendererInfo.Width = chartRect.Width - cri.yAxisRendererInfo.Width;
cri.yAxisRendererInfo.X = chartRect.Left;
cri.yAxisRendererInfo.Y = chartRect.Top;
cri.yAxisRendererInfo.Height = cri.xAxisRendererInfo.Y - chartRect.Top;
cri.plotAreaRendererInfo.X = cri.xAxisRendererInfo.X;
cri.plotAreaRendererInfo.Y = cri.yAxisRendererInfo.InnerRect.Y;
cri.plotAreaRendererInfo.Width = cri.xAxisRendererInfo.Width;
cri.plotAreaRendererInfo.Height = cri.yAxisRendererInfo.InnerRect.Height;
}
}
}

View File

@@ -0,0 +1,134 @@
#region PDFsharp Charting - A .NET charting library based on PDFsharp
//
// Authors:
// Niklas Schneider
//
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.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 PdfSharp.Drawing;
namespace PdfSharp.Charting.Renderers
{
/// <summary>
/// Represents gridlines used by column or line charts, i. e. X axis grid will be rendered
/// from top to bottom and Y axis grid will be rendered from left to right of the plot area.
/// </summary>
internal class ColumnLikeGridlinesRenderer : GridlinesRenderer
{
/// <summary>
/// Initializes a new instance of the ColumnLikeGridlinesRenderer class with the
/// specified renderer parameters.
/// </summary>
internal ColumnLikeGridlinesRenderer(RendererParameters parms)
: base(parms)
{ }
/// <summary>
/// Draws the gridlines into the plot area.
/// </summary>
internal override void Draw()
{
ChartRendererInfo cri = (ChartRendererInfo)_rendererParms.RendererInfo;
XRect plotAreaRect = cri.plotAreaRendererInfo.Rect;
if (plotAreaRect.IsEmpty)
return;
AxisRendererInfo xari = cri.xAxisRendererInfo;
AxisRendererInfo yari = cri.yAxisRendererInfo;
double xMin = xari.MinimumScale;
double xMax = xari.MaximumScale;
double yMin = yari.MinimumScale;
double yMax = yari.MaximumScale;
double xMajorTick = xari.MajorTick;
double yMajorTick = yari.MajorTick;
double xMinorTick = xari.MinorTick;
double yMinorTick = yari.MinorTick;
XMatrix matrix = cri.plotAreaRendererInfo._matrix;
LineFormatRenderer lineFormatRenderer;
XGraphics gfx = _rendererParms.Graphics;
XPoint[] points = new XPoint[2];
if (xari.MinorGridlinesLineFormat != null)
{
lineFormatRenderer = new LineFormatRenderer(gfx, xari.MinorGridlinesLineFormat);
for (double x = xMin + xMinorTick; x < xMax; x += xMinorTick)
{
points[0].X = x;
points[0].Y = yMin;
points[1].X = x;
points[1].Y = yMax;
matrix.TransformPoints(points);
lineFormatRenderer.DrawLine(points[0], points[1]);
}
}
if (xari.MajorGridlinesLineFormat != null)
{
lineFormatRenderer = new LineFormatRenderer(gfx, xari.MajorGridlinesLineFormat);
for (double x = xMin; x <= xMax; x += xMajorTick)
{
points[0].X = x;
points[0].Y = yMin;
points[1].X = x;
points[1].Y = yMax;
matrix.TransformPoints(points);
lineFormatRenderer.DrawLine(points[0], points[1]);
}
}
if (yari.MinorGridlinesLineFormat != null)
{
lineFormatRenderer = new LineFormatRenderer(gfx, yari.MinorGridlinesLineFormat);
for (double y = yMin + yMinorTick; y < yMax; y += yMinorTick)
{
points[0].X = xMin;
points[0].Y = y;
points[1].X = xMax;
points[1].Y = y;
matrix.TransformPoints(points);
lineFormatRenderer.DrawLine(points[0], points[1]);
}
}
if (yari.MajorGridlinesLineFormat != null)
{
lineFormatRenderer = new LineFormatRenderer(gfx, yari.MajorGridlinesLineFormat);
for (double y = yMin; y <= yMax; y += yMajorTick)
{
points[0].X = xMin;
points[0].Y = y;
points[1].X = xMax;
points[1].Y = y;
matrix.TransformPoints(points);
lineFormatRenderer.DrawLine(points[0], points[1]);
}
}
}
}
}

View File

@@ -0,0 +1,96 @@
#region PDFsharp Charting - A .NET charting library based on PDFsharp
//
// Authors:
// Niklas Schneider
//
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.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 PdfSharp.Drawing;
namespace PdfSharp.Charting.Renderers
{
/// <summary>
/// Represents the legend renderer specific to charts like column, line, or bar.
/// </summary>
internal class ColumnLikeLegendRenderer : LegendRenderer
{
/// <summary>
/// Initializes a new instance of the ColumnLikeLegendRenderer class with the
/// specified renderer parameters.
/// </summary>
internal ColumnLikeLegendRenderer(RendererParameters parms)
: base(parms)
{ }
/// <summary>
/// Initializes the legend's renderer info. Each data series will be represented through
/// a legend entry renderer info.
/// </summary>
internal override RendererInfo Init()
{
LegendRendererInfo lri = null;
ChartRendererInfo cri = (ChartRendererInfo)_rendererParms.RendererInfo;
if (cri._chart._legend != null)
{
lri = new LegendRendererInfo();
lri._legend = cri._chart._legend;
lri.Font = Converter.ToXFont(lri._legend._font, cri.DefaultFont);
lri.FontColor = new XSolidBrush(XColors.Black);
if (lri._legend._lineFormat != null)
lri.BorderPen = Converter.ToXPen(lri._legend._lineFormat, XColors.Black, DefaultLineWidth, XDashStyle.Solid);
lri.Entries = new LegendEntryRendererInfo[cri.seriesRendererInfos.Length];
int index = 0;
foreach (SeriesRendererInfo sri in cri.seriesRendererInfos)
{
LegendEntryRendererInfo leri = new LegendEntryRendererInfo();
leri._seriesRendererInfo = sri;
leri._legendRendererInfo = lri;
leri.EntryText = sri._series.Name;
if (sri._markerRendererInfo != null)
{
leri.MarkerSize.Width = leri.MarkerSize.Height = sri._markerRendererInfo.MarkerSize.Point;
leri.MarkerPen = new XPen(sri._markerRendererInfo.MarkerForegroundColor);
leri.MarkerBrush = new XSolidBrush(sri._markerRendererInfo.MarkerBackgroundColor);
}
else
{
leri.MarkerPen = sri.LineFormat;
leri.MarkerBrush = sri.FillFormat;
}
if (cri._chart._type == ChartType.ColumnStacked2D)
// Stacked columns are in reverse order.
lri.Entries[cri.seriesRendererInfos.Length - index++ - 1] = leri;
else
lri.Entries[index++] = leri;
}
}
return lri;
}
}
}

View File

@@ -0,0 +1,68 @@
#region PDFsharp Charting - A .NET charting library based on PDFsharp
//
// Authors:
// Niklas Schneider
//
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.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 PdfSharp.Drawing;
namespace PdfSharp.Charting.Renderers
{
/// <summary>
/// Base class for all plot area renderers.
/// </summary>
internal abstract class ColumnLikePlotAreaRenderer : PlotAreaRenderer
{
/// <summary>
/// Initializes a new instance of the ColumnLikePlotAreaRenderer class with the
/// specified renderer parameters.
/// </summary>
internal ColumnLikePlotAreaRenderer(RendererParameters parms)
: base(parms)
{ }
/// <summary>
/// Layouts and calculates the space for column like plot areas.
/// </summary>
internal override void Format()
{
ChartRendererInfo cri = (ChartRendererInfo)_rendererParms.RendererInfo;
double xMin = cri.xAxisRendererInfo.MinimumScale;
double xMax = cri.xAxisRendererInfo.MaximumScale;
double yMin = cri.yAxisRendererInfo.MinimumScale;
double yMax = cri.yAxisRendererInfo.MaximumScale;
XRect plotAreaBox = cri.plotAreaRendererInfo.Rect;
cri.plotAreaRendererInfo._matrix = new XMatrix();
cri.plotAreaRendererInfo._matrix.TranslatePrepend(-xMin, yMax);
cri.plotAreaRendererInfo._matrix.Scale(plotAreaBox.Width / xMax, plotAreaBox.Height / (yMax - yMin), XMatrixOrder.Append);
cri.plotAreaRendererInfo._matrix.ScalePrepend(1, -1);
cri.plotAreaRendererInfo._matrix.Translate(plotAreaBox.X, plotAreaBox.Y, XMatrixOrder.Append);
}
}
}

View File

@@ -0,0 +1,139 @@
#region PDFsharp Charting - A .NET charting library based on PDFsharp
//
// Authors:
// Niklas Schneider
//
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.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 PdfSharp.Drawing;
namespace PdfSharp.Charting.Renderers
{
/// <summary>
/// Represents a plot area renderer of clustered columns, i. e. all columns are drawn side by side.
/// </summary>
internal abstract class ColumnPlotAreaRenderer : ColumnLikePlotAreaRenderer
{
/// <summary>
/// Initializes a new instance of the ColumnPlotAreaRenderer class with the
/// specified renderer parameters.
/// </summary>
internal ColumnPlotAreaRenderer(RendererParameters parms)
: base(parms)
{ }
/// <summary>
/// Layouts and calculates the space for each column.
/// </summary>
internal override void Format()
{
base.Format();
CalcColumns();
}
/// <summary>
/// Draws the content of the column plot area.
/// </summary>
internal override void Draw()
{
ChartRendererInfo cri = (ChartRendererInfo)_rendererParms.RendererInfo;
XRect plotAreaBox = cri.plotAreaRendererInfo.Rect;
if (plotAreaBox.IsEmpty)
return;
XGraphics gfx = _rendererParms.Graphics;
double xMin = cri.xAxisRendererInfo.MinimumScale;
double xMax = cri.xAxisRendererInfo.MaximumScale;
double yMin = cri.yAxisRendererInfo.MinimumScale;
double yMax = cri.yAxisRendererInfo.MaximumScale;
LineFormatRenderer lineFormatRenderer;
// Under some circumstances it is possible that no zero base line will be drawn,
// e. g. because of unfavourable minimum/maximum scale and/or major tick, so force to draw
// a zero base line if necessary.
if (cri.yAxisRendererInfo.MajorGridlinesLineFormat != null ||
cri.yAxisRendererInfo.MinorGridlinesLineFormat != null)
{
if (yMin < 0 && yMax > 0)
{
XPoint[] points = new XPoint[2];
points[0].X = xMin;
points[0].Y = 0;
points[1].X = xMax;
points[1].Y = 0;
cri.plotAreaRendererInfo._matrix.TransformPoints(points);
if (cri.yAxisRendererInfo.MinorGridlinesLineFormat != null)
lineFormatRenderer = new LineFormatRenderer(gfx, cri.yAxisRendererInfo.MinorGridlinesLineFormat);
else
lineFormatRenderer = new LineFormatRenderer(gfx, cri.yAxisRendererInfo.MajorGridlinesLineFormat);
lineFormatRenderer.DrawLine(points[0], points[1]);
}
}
// Draw columns
XGraphicsState state = gfx.Save();
foreach (SeriesRendererInfo sri in cri.seriesRendererInfos)
{
foreach (ColumnRendererInfo column in sri._pointRendererInfos)
{
// Do not draw column if value is outside yMin/yMax range. Clipping does not make sense.
if (IsDataInside(yMin, yMax, column.Point._value))
gfx.DrawRectangle(column.FillFormat, column.Rect);
}
}
// Draw borders around column.
// A border can overlap neighbor columns, so it is important to draw borders at the end.
foreach (SeriesRendererInfo sri in cri.seriesRendererInfos)
{
foreach (ColumnRendererInfo column in sri._pointRendererInfos)
{
// Do not draw column if value is outside yMin/yMax range. Clipping does not make sense.
if (IsDataInside(yMin, yMax, column.Point._value) && column.LineFormat.Width > 0)
{
lineFormatRenderer = new LineFormatRenderer(gfx, column.LineFormat);
lineFormatRenderer.DrawRectangle(column.Rect);
}
}
}
gfx.Restore(state);
}
/// <summary>
/// Calculates the position, width and height of each column of all series.
/// </summary>
protected abstract void CalcColumns();
/// <summary>
/// If yValue is within the range from yMin to yMax returns true, otherwise false.
/// </summary>
protected abstract bool IsDataInside(double yMin, double yMax, double yValue);
}
}

View File

@@ -0,0 +1,124 @@
#region PDFsharp Charting - A .NET charting library based on PDFsharp
//
// Authors:
// Niklas Schneider
//
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.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 System;
using PdfSharp.Drawing;
namespace PdfSharp.Charting.Renderers
{
/// <summary>
/// Represents a plot area renderer of stacked columns, i. e. all columns are drawn one on another.
/// </summary>
internal class ColumnStackedPlotAreaRenderer : ColumnPlotAreaRenderer
{
/// <summary>
/// Initializes a new instance of the ColumnStackedPlotAreaRenderer class with the
/// specified renderer parameters.
/// </summary>
internal ColumnStackedPlotAreaRenderer(RendererParameters parms)
: base(parms)
{ }
/// <summary>
/// Calculates the position, width and height of each column of all series.
/// </summary>
protected override void CalcColumns()
{
ChartRendererInfo cri = (ChartRendererInfo)_rendererParms.RendererInfo;
if (cri.seriesRendererInfos.Length == 0)
return;
double xMin = cri.xAxisRendererInfo.MinimumScale;
double xMajorTick = cri.xAxisRendererInfo.MajorTick;
int maxPoints = 0;
foreach (SeriesRendererInfo sri in cri.seriesRendererInfos)
maxPoints = Math.Max(maxPoints, sri._series._seriesElements.Count);
double x = xMin + xMajorTick / 2;
// Space used by one column.
double columnWidth = xMajorTick * 0.75 / 2;
XPoint[] points = new XPoint[2];
for (int pointIdx = 0; pointIdx < maxPoints; ++pointIdx)
{
// Set x to first clustered column for each series.
double yMin = 0, yMax = 0, y0 = 0, y1 = 0;
double x0 = x - columnWidth;
double x1 = x + columnWidth;
foreach (SeriesRendererInfo sri in cri.seriesRendererInfos)
{
if (sri._pointRendererInfos.Length <= pointIdx)
break;
ColumnRendererInfo column = (ColumnRendererInfo)sri._pointRendererInfos[pointIdx];
if (column.Point != null && !double.IsNaN(column.Point._value))
{
double y = column.Point._value;
if (y < 0)
{
y0 = yMin + y;
y1 = yMin;
yMin += y;
}
else
{
y0 = yMax;
y1 = yMax + y;
yMax += y;
}
points[0].X = x0; // upper left
points[0].Y = y1;
points[1].X = x1; // lower right
points[1].Y = y0;
cri.plotAreaRendererInfo._matrix.TransformPoints(points);
column.Rect = new XRect(points[0].X,
points[0].Y,
points[1].X - points[0].X,
points[1].Y - points[0].Y);
}
}
x++; // Next stacked column.
}
}
/// <summary>
/// Stacked columns are always inside.
/// </summary>
protected override bool IsDataInside(double yMin, double yMax, double yValue)
{
return true;
}
}
}

View File

@@ -0,0 +1,295 @@
#region PDFsharp Charting - A .NET charting library based on PDFsharp
//
// Authors:
// Niklas Schneider
//
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.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 System;
using System.Collections.Generic;
using PdfSharp.Drawing;
namespace PdfSharp.Charting.Renderers
{
/// <summary>
/// Represents a renderer for combinations of charts.
/// </summary>
internal class CombinationChartRenderer : ChartRenderer
{
/// <summary>
/// Initializes a new instance of the CombinationChartRenderer class with the
/// specified renderer parameters.
/// </summary>
internal CombinationChartRenderer(RendererParameters parms)
: base(parms)
{ }
/// <summary>
/// Returns an initialized and renderer specific rendererInfo.
/// </summary>
internal override RendererInfo Init()
{
CombinationRendererInfo cri = new CombinationRendererInfo();
cri._chart = (Chart)_rendererParms.DrawingItem;
_rendererParms.RendererInfo = cri;
InitSeriesRendererInfo();
DistributeSeries();
if (cri._areaSeriesRendererInfos != null)
{
cri.seriesRendererInfos = cri._areaSeriesRendererInfos;
AreaChartRenderer renderer = new AreaChartRenderer(_rendererParms);
renderer.InitSeries();
}
if (cri._columnSeriesRendererInfos != null)
{
cri.seriesRendererInfos = cri._columnSeriesRendererInfos;
ColumnChartRenderer renderer = new ColumnChartRenderer(_rendererParms);
renderer.InitSeries();
}
if (cri._lineSeriesRendererInfos != null)
{
cri.seriesRendererInfos = cri._lineSeriesRendererInfos;
LineChartRenderer renderer = new LineChartRenderer(_rendererParms);
renderer.InitSeries();
}
cri.seriesRendererInfos = cri._commonSeriesRendererInfos;
LegendRenderer lr = new ColumnLikeLegendRenderer(_rendererParms);
cri.legendRendererInfo = (LegendRendererInfo)lr.Init();
AxisRenderer xar = new HorizontalXAxisRenderer(_rendererParms);
cri.xAxisRendererInfo = (AxisRendererInfo)xar.Init();
AxisRenderer yar = new VerticalYAxisRenderer(_rendererParms);
cri.yAxisRendererInfo = (AxisRendererInfo)yar.Init();
PlotArea plotArea = cri._chart.PlotArea;
PlotAreaRenderer apar = new AreaPlotAreaRenderer(_rendererParms);
cri.plotAreaRendererInfo = (PlotAreaRendererInfo)apar.Init();
// Draw data labels.
if (cri._columnSeriesRendererInfos != null)
{
cri.seriesRendererInfos = cri._columnSeriesRendererInfos;
DataLabelRenderer dlr = new ColumnDataLabelRenderer(_rendererParms);
dlr.Init();
}
return cri;
}
/// <summary>
/// Layouts and calculates the space used by the combination chart.
/// </summary>
internal override void Format()
{
CombinationRendererInfo cri = (CombinationRendererInfo)_rendererParms.RendererInfo;
cri.seriesRendererInfos = cri._commonSeriesRendererInfos;
LegendRenderer lr = new ColumnLikeLegendRenderer(_rendererParms);
lr.Format();
// axes
AxisRenderer xar = new HorizontalXAxisRenderer(_rendererParms);
xar.Format();
AxisRenderer yar = new VerticalYAxisRenderer(_rendererParms);
yar.Format();
// Calculate rects and positions.
XRect chartRect = LayoutLegend();
cri.xAxisRendererInfo.X = chartRect.Left + cri.yAxisRendererInfo.Width;
cri.xAxisRendererInfo.Y = chartRect.Bottom - cri.xAxisRendererInfo.Height;
cri.xAxisRendererInfo.Width = chartRect.Width - cri.yAxisRendererInfo.Width;
cri.yAxisRendererInfo.X = chartRect.Left;
cri.yAxisRendererInfo.Y = chartRect.Top;
cri.yAxisRendererInfo.Height = chartRect.Height - cri.xAxisRendererInfo.Height;
cri.plotAreaRendererInfo.X = cri.xAxisRendererInfo.X;
cri.plotAreaRendererInfo.Y = cri.yAxisRendererInfo.InnerRect.Y;
cri.plotAreaRendererInfo.Width = cri.xAxisRendererInfo.Width;
cri.plotAreaRendererInfo.Height = cri.yAxisRendererInfo.InnerRect.Height;
// Calculated remaining plot area, now it's safe to format.
PlotAreaRenderer renderer;
if (cri._areaSeriesRendererInfos != null)
{
cri.seriesRendererInfos = cri._areaSeriesRendererInfos;
renderer = new AreaPlotAreaRenderer(_rendererParms);
renderer.Format();
}
if (cri._columnSeriesRendererInfos != null)
{
cri.seriesRendererInfos = cri._columnSeriesRendererInfos;
//TODO Check for Clustered- or StackedPlotAreaRenderer
renderer = new ColumnClusteredPlotAreaRenderer(_rendererParms);
renderer.Format();
}
if (cri._lineSeriesRendererInfos != null)
{
cri.seriesRendererInfos = cri._lineSeriesRendererInfos;
renderer = new LinePlotAreaRenderer(_rendererParms);
renderer.Format();
}
// Draw data labels.
if (cri._columnSeriesRendererInfos != null)
{
cri.seriesRendererInfos = cri._columnSeriesRendererInfos;
DataLabelRenderer dlr = new ColumnDataLabelRenderer(_rendererParms);
dlr.Format();
}
}
/// <summary>
/// Draws the column chart.
/// </summary>
internal override void Draw()
{
CombinationRendererInfo cri = (CombinationRendererInfo)_rendererParms.RendererInfo;
cri.seriesRendererInfos = cri._commonSeriesRendererInfos;
LegendRenderer lr = new ColumnLikeLegendRenderer(_rendererParms);
lr.Draw();
WallRenderer wr = new WallRenderer(_rendererParms);
wr.Draw();
GridlinesRenderer glr = new ColumnLikeGridlinesRenderer(_rendererParms);
glr.Draw();
PlotAreaBorderRenderer pabr = new PlotAreaBorderRenderer(_rendererParms);
pabr.Draw();
PlotAreaRenderer renderer;
if (cri._areaSeriesRendererInfos != null)
{
cri.seriesRendererInfos = cri._areaSeriesRendererInfos;
renderer = new AreaPlotAreaRenderer(_rendererParms);
renderer.Draw();
}
if (cri._columnSeriesRendererInfos != null)
{
cri.seriesRendererInfos = cri._columnSeriesRendererInfos;
//TODO Check for Clustered- or StackedPlotAreaRenderer
renderer = new ColumnClusteredPlotAreaRenderer(_rendererParms);
renderer.Draw();
}
if (cri._lineSeriesRendererInfos != null)
{
cri.seriesRendererInfos = cri._lineSeriesRendererInfos;
renderer = new LinePlotAreaRenderer(_rendererParms);
renderer.Draw();
}
// Draw data labels.
if (cri._columnSeriesRendererInfos != null)
{
cri.seriesRendererInfos = cri._columnSeriesRendererInfos;
DataLabelRenderer dlr = new ColumnDataLabelRenderer(_rendererParms);
dlr.Draw();
}
// Draw axes.
cri.seriesRendererInfos = cri._commonSeriesRendererInfos;
if (cri.xAxisRendererInfo._axis != null)
{
AxisRenderer xar = new HorizontalXAxisRenderer(_rendererParms);
xar.Draw();
}
if (cri.yAxisRendererInfo._axis != null)
{
AxisRenderer yar = new VerticalYAxisRenderer(_rendererParms);
yar.Draw();
}
}
/// <summary>
/// Initializes all necessary data to draw series for a combination chart.
/// </summary>
private void InitSeriesRendererInfo()
{
CombinationRendererInfo cri = (CombinationRendererInfo)_rendererParms.RendererInfo;
SeriesCollection seriesColl = cri._chart.SeriesCollection;
cri.seriesRendererInfos = new SeriesRendererInfo[seriesColl.Count];
for (int idx = 0; idx < seriesColl.Count; ++idx)
{
SeriesRendererInfo sri = new SeriesRendererInfo();
sri._series = seriesColl[idx];
cri.seriesRendererInfos[idx] = sri;
}
}
/// <summary>
/// Sort all series renderer info dependent on their chart type.
/// </summary>
private void DistributeSeries()
{
CombinationRendererInfo cri = (CombinationRendererInfo)_rendererParms.RendererInfo;
List<SeriesRendererInfo> areaSeries = new List<SeriesRendererInfo>();
List<SeriesRendererInfo> columnSeries = new List<SeriesRendererInfo>();
List<SeriesRendererInfo> lineSeries = new List<SeriesRendererInfo>();
foreach (SeriesRendererInfo sri in cri.seriesRendererInfos)
{
switch (sri._series._chartType)
{
case ChartType.Area2D:
areaSeries.Add(sri);
break;
case ChartType.Column2D:
columnSeries.Add(sri);
break;
case ChartType.Line:
lineSeries.Add(sri);
break;
default:
throw new InvalidOperationException(PSCSR.InvalidChartTypeForCombination(sri._series._chartType));
}
}
cri._commonSeriesRendererInfos = cri.seriesRendererInfos;
if (areaSeries.Count > 0)
{
cri._areaSeriesRendererInfos = new SeriesRendererInfo[areaSeries.Count];
areaSeries.CopyTo(cri._areaSeriesRendererInfos);
}
if (columnSeries.Count > 0)
{
cri._columnSeriesRendererInfos = new SeriesRendererInfo[columnSeries.Count];
columnSeries.CopyTo(cri._columnSeriesRendererInfos);
}
if (lineSeries.Count > 0)
{
cri._lineSeriesRendererInfos = new SeriesRendererInfo[lineSeries.Count];
lineSeries.CopyTo(cri._lineSeriesRendererInfos);
}
}
}
}

View File

@@ -0,0 +1,138 @@
#region PDFsharp Charting - A .NET charting library based on PDFsharp
//
// Authors:
// Niklas Schneider
//
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.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 PdfSharp.Drawing;
namespace PdfSharp.Charting.Renderers
{
/// <summary>
/// Provides functions which converts Charting.DOM objects into PdfSharp.Drawing objects.
/// </summary>
internal class Converter
{
/// <summary>
/// Creates a XFont based on the font. Missing attributes will be taken from the defaultFont
/// parameter.
/// </summary>
internal static XFont ToXFont(Font font, XFont defaultFont)
{
XFont xfont = defaultFont;
if (font != null)
{
string fontFamily = font.Name;
if (fontFamily == "")
fontFamily = defaultFont.FontFamily.Name;
XFontStyle fontStyle = defaultFont.Style;
if (font._bold)
fontStyle |= XFontStyle.Bold;
if (font._italic)
fontStyle |= XFontStyle.Italic;
double size = font._size.Point; //emSize???
if (size == 0)
size = defaultFont.Size;
xfont = new XFont(fontFamily, size, fontStyle);
}
return xfont;
}
/// <summary>
/// Creates a XPen based on the specified line format. If not specified color and width will be taken
/// from the defaultColor and defaultWidth parameter.
/// </summary>
internal static XPen ToXPen(LineFormat lineFormat, XColor defaultColor, double defaultWidth)
{
return ToXPen(lineFormat, defaultColor, defaultWidth, XDashStyle.Solid);
}
/// <summary>
/// Creates a XPen based on the specified line format. If not specified color and width will be taken
/// from the defaultPen parameter.
/// </summary>
internal static XPen ToXPen(LineFormat lineFormat, XPen defaultPen)
{
return ToXPen(lineFormat, defaultPen.Color, defaultPen.Width, defaultPen.DashStyle);
}
/// <summary>
/// Creates a XPen based on the specified line format. If not specified color, width and dash style
/// will be taken from the defaultColor, defaultWidth and defaultDashStyle parameters.
/// </summary>
internal static XPen ToXPen(LineFormat lineFormat, XColor defaultColor, double defaultWidth, XDashStyle defaultDashStyle)
{
XPen pen = null;
if (lineFormat == null)
{
pen = new XPen(defaultColor, defaultWidth);
pen.DashStyle = defaultDashStyle;
}
else
{
XColor color = defaultColor;
if (!lineFormat.Color.IsEmpty)
color = lineFormat.Color;
double width = lineFormat.Width.Point;
if (!lineFormat.Visible)
width = 0;
if (lineFormat.Visible && width == 0)
width = defaultWidth;
pen = new XPen(color, width);
pen.DashStyle = lineFormat._dashStyle;
pen.DashOffset = 10 * width;
}
return pen;
}
/// <summary>
/// Creates a XBrush based on the specified fill format. If not specified, color will be taken
/// from the defaultColor parameter.
/// </summary>
internal static XBrush ToXBrush(FillFormat fillFormat, XColor defaultColor)
{
if (fillFormat == null || fillFormat._color.IsEmpty)
return new XSolidBrush(defaultColor);
return new XSolidBrush(fillFormat._color);
}
/// <summary>
/// Creates a XBrush based on the specified font color. If not specified, color will be taken
/// from the defaultColor parameter.
/// </summary>
internal static XBrush ToXBrush(Font font, XColor defaultColor)
{
if (font == null || font._color.IsEmpty)
return new XSolidBrush(defaultColor);
return new XSolidBrush(font._color);
}
}
}

View File

@@ -0,0 +1,107 @@
#region PDFsharp Charting - A .NET charting library based on PDFsharp
//
// Authors:
// Niklas Schneider
//
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.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 PdfSharp.Drawing;
namespace PdfSharp.Charting.Renderers
{
/// <summary>
/// Represents a data label renderer.
/// </summary>
internal abstract class DataLabelRenderer : Renderer
{
/// <summary>
/// Initializes a new instance of the DataLabelRenderer class with the
/// specified renderer parameters.
/// </summary>
internal DataLabelRenderer(RendererParameters parms)
: base(parms)
{ }
/// <summary>
/// Creates a data label rendererInfo.
/// Does not return any renderer info.
/// </summary>
internal override RendererInfo Init()
{
ChartRendererInfo cri = (ChartRendererInfo)_rendererParms.RendererInfo;
foreach (SeriesRendererInfo sri in cri.seriesRendererInfos)
{
if (cri._chart._hasDataLabel || cri._chart._dataLabel != null ||
sri._series._hasDataLabel || sri._series._dataLabel != null)
{
DataLabelRendererInfo dlri = new DataLabelRendererInfo();
DataLabel dl = sri._series._dataLabel;
if (dl == null)
dl = cri._chart._dataLabel;
if (dl == null)
{
dlri.Format = "0";
dlri.Font = cri.DefaultDataLabelFont;
dlri.FontColor = new XSolidBrush(XColors.Black);
dlri.Position = DataLabelPosition.InsideEnd;
if (cri._chart._type == ChartType.Pie2D || cri._chart._type == ChartType.PieExploded2D)
dlri.Type = DataLabelType.Percent;
else
dlri.Type = DataLabelType.Value;
}
else
{
dlri.Format = dl.Format.Length > 0 ? dl.Format : "0";
dlri.Font = Converter.ToXFont(dl._font, cri.DefaultDataLabelFont);
dlri.FontColor = Converter.ToXBrush(dl._font, XColors.Black);
if (dl._positionInitialized)
dlri.Position = dl._position;
else
dlri.Position = DataLabelPosition.OutsideEnd;
if (dl._typeInitialized)
dlri.Type = dl._type;
else
{
if (cri._chart._type == ChartType.Pie2D || cri._chart._type == ChartType.PieExploded2D)
dlri.Type = DataLabelType.Percent;
else
dlri.Type = DataLabelType.Value;
}
}
sri._dataLabelRendererInfo = dlri;
}
}
return null;
}
/// <summary>
/// Calculates the specific positions for each data label.
/// </summary>
internal abstract void CalcPositions();
}
}

View File

@@ -0,0 +1,44 @@
#region PDFsharp Charting - A .NET charting library based on PDFsharp
//
// Authors:
// Niklas Schneider
//
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.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
namespace PdfSharp.Charting.Renderers
{
/// <summary>
/// Base class for all renderers used to draw gridlines.
/// </summary>
internal abstract class GridlinesRenderer : Renderer
{
/// <summary>
/// Initializes a new instance of the GridlinesRenderer class with the specified renderer parameters.
/// </summary>
internal GridlinesRenderer(RendererParameters parms)
: base(parms)
{ }
}
}

View File

@@ -0,0 +1,84 @@
#region PDFsharp Charting - A .NET charting library based on PDFsharp
//
// Authors:
// Niklas Schneider
//
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.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 System;
namespace PdfSharp.Charting.Renderers
{
/// <summary>
/// Represents a Y axis renderer used for charts of type BarStacked2D.
/// </summary>
internal class HorizontalStackedYAxisRenderer : HorizontalYAxisRenderer
{
/// <summary>
/// Initializes a new instance of the HorizontalStackedYAxisRenderer class with the
/// specified renderer parameters.
/// </summary>
internal HorizontalStackedYAxisRenderer(RendererParameters parms)
: base(parms)
{ }
/// <summary>
/// Determines the sum of the smallest and the largest stacked bar
/// from all series of the chart.
/// </summary>
protected override void CalcYAxis(out double yMin, out double yMax)
{
yMin = double.MaxValue;
yMax = double.MinValue;
ChartRendererInfo cri = (ChartRendererInfo)_rendererParms.RendererInfo;
int maxPoints = 0;
foreach (SeriesRendererInfo sri in cri.seriesRendererInfos)
maxPoints = Math.Max(maxPoints, sri._series._seriesElements.Count);
for (int pointIdx = 0; pointIdx < maxPoints; ++pointIdx)
{
double valueSumPos = 0, valueSumNeg = 0;
foreach (SeriesRendererInfo sri in cri.seriesRendererInfos)
{
if (sri._pointRendererInfos.Length <= pointIdx)
break;
ColumnRendererInfo column = (ColumnRendererInfo)sri._pointRendererInfos[pointIdx];
if (column.Point != null && !double.IsNaN(column.Point._value))
{
if (column.Point._value < 0)
valueSumNeg += column.Point._value;
else
valueSumPos += column.Point._value;
}
}
yMin = Math.Min(valueSumNeg, yMin);
yMax = Math.Max(valueSumPos, yMax);
}
}
}
}

View File

@@ -0,0 +1,314 @@
#region PDFsharp Charting - A .NET charting library based on PDFsharp
//
// Authors:
// Niklas Schneider
//
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.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 System;
using PdfSharp.Drawing;
namespace PdfSharp.Charting.Renderers
{
/// <summary>
/// Represents an axis renderer used for charts of type Column2D or Line.
/// </summary>
internal class HorizontalXAxisRenderer : XAxisRenderer
{
/// <summary>
/// Initializes a new instance of the HorizontalXAxisRenderer class with the specified renderer parameters.
/// </summary>
internal HorizontalXAxisRenderer(RendererParameters parms)
: base(parms)
{ }
/// <summary>
/// Returns an initialized rendererInfo based on the X axis.
/// </summary>
internal override RendererInfo Init()
{
Chart chart = (Chart)_rendererParms.DrawingItem;
AxisRendererInfo xari = new AxisRendererInfo();
xari._axis = chart._xAxis;
if (xari._axis != null)
{
ChartRendererInfo cri = (ChartRendererInfo)_rendererParms.RendererInfo;
CalculateXAxisValues(xari);
InitTickLabels(xari, cri.DefaultFont);
InitXValues(xari);
InitAxisTitle(xari, cri.DefaultFont);
InitAxisLineFormat(xari);
InitGridlines(xari);
}
return xari;
}
/// <summary>
/// Calculates the space used for the X axis.
/// </summary>
internal override void Format()
{
AxisRendererInfo xari = ((ChartRendererInfo)_rendererParms.RendererInfo).xAxisRendererInfo;
if (xari._axis != null)
{
AxisTitleRendererInfo atri = xari._axisTitleRendererInfo;
// Calculate space used for axis title.
XSize titleSize = new XSize(0, 0);
if (atri != null && atri.AxisTitleText != null && atri.AxisTitleText.Length > 0)
{
titleSize = _rendererParms.Graphics.MeasureString(atri.AxisTitleText, atri.AxisTitleFont);
atri.AxisTitleSize = titleSize;
}
// Calculate space used for tick labels.
XSize size = new XSize(0, 0);
if (xari.XValues.Count > 0)
{
XSeries xs = xari.XValues[0];
foreach (XValue xv in xs)
{
if (xv != null)
{
string tickLabel = xv._value;
XSize valueSize = _rendererParms.Graphics.MeasureString(tickLabel, xari.TickLabelsFont);
size.Height = Math.Max(valueSize.Height, size.Height);
size.Width += valueSize.Width;
}
}
}
// Remember space for later drawing.
xari.TickLabelsHeight = size.Height;
xari.Height = titleSize.Height + size.Height + xari.MajorTickMarkWidth;
xari.Width = Math.Max(titleSize.Width, size.Width);
}
}
/// <summary>
/// Draws the horizontal X axis.
/// </summary>
internal override void Draw()
{
XGraphics gfx = _rendererParms.Graphics;
ChartRendererInfo cri = (ChartRendererInfo)_rendererParms.RendererInfo;
AxisRendererInfo xari = cri.xAxisRendererInfo;
double xMin = xari.MinimumScale;
double xMax = xari.MaximumScale;
double xMajorTick = xari.MajorTick;
double xMinorTick = xari.MinorTick;
double xMaxExtension = xari.MajorTick;
// Draw tick labels. Each tick label will be aligned centered.
int countTickLabels = (int)xMax;
double tickLabelStep = xari.Width;
if (countTickLabels != 0)
tickLabelStep = xari.Width / countTickLabels;
//XPoint startPos = new XPoint(xari.X + tickLabelStep / 2, xari.Y + /*xari.TickLabelsHeight +*/ xari.MajorTickMarkWidth);
XPoint startPos = new XPoint(xari.X + tickLabelStep / 2, xari.Y + xari.TickLabelsHeight);
if (xari.MajorTickMark != TickMarkType.None)
startPos.Y += xari.MajorTickMarkWidth;
foreach (XSeries xs in xari.XValues)
{
for (int idx = 0; idx < countTickLabels && idx < xs.Count; ++idx)
{
XValue xv = xs[idx];
if (xv != null)
{
string tickLabel = xv._value;
XSize size = gfx.MeasureString(tickLabel, xari.TickLabelsFont);
gfx.DrawString(tickLabel, xari.TickLabelsFont, xari.TickLabelsBrush, startPos.X - size.Width / 2, startPos.Y);
}
startPos.X += tickLabelStep;
}
}
// Draw axis.
// First draw tick marks, second draw axis.
double majorTickMarkStart = 0, majorTickMarkEnd = 0,
minorTickMarkStart = 0, minorTickMarkEnd = 0;
GetTickMarkPos(xari, ref majorTickMarkStart, ref majorTickMarkEnd, ref minorTickMarkStart, ref minorTickMarkEnd);
LineFormatRenderer lineFormatRenderer = new LineFormatRenderer(gfx, xari.LineFormat);
XPoint[] points = new XPoint[2];
// Minor ticks.
if (xari.MinorTickMark != TickMarkType.None)
{
int countMinorTickMarks = (int)(xMax / xMinorTick);
double minorTickMarkStep = xari.Width / countMinorTickMarks;
startPos.X = xari.X;
for (int x = 0; x <= countMinorTickMarks; x++)
{
points[0].X = startPos.X + minorTickMarkStep * x;
points[0].Y = minorTickMarkStart;
points[1].X = points[0].X;
points[1].Y = minorTickMarkEnd;
lineFormatRenderer.DrawLine(points[0], points[1]);
}
}
// Major ticks.
if (xari.MajorTickMark != TickMarkType.None)
{
int countMajorTickMarks = (int)(xMax / xMajorTick);
double majorTickMarkStep = xari.Width;
if (countMajorTickMarks != 0)
majorTickMarkStep = xari.Width / countMajorTickMarks;
startPos.X = xari.X;
for (int x = 0; x <= countMajorTickMarks; x++)
{
points[0].X = startPos.X + majorTickMarkStep * x;
points[0].Y = majorTickMarkStart;
points[1].X = points[0].X;
points[1].Y = majorTickMarkEnd;
lineFormatRenderer.DrawLine(points[0], points[1]);
}
}
// Axis.
if (xari.LineFormat != null)
{
points[0].X = xari.X;
points[0].Y = xari.Y;
points[1].X = xari.X + xari.Width;
points[1].Y = xari.Y;
if (xari.MajorTickMark != TickMarkType.None)
{
points[0].X -= xari.LineFormat.Width / 2;
points[1].X += xari.LineFormat.Width / 2;
}
lineFormatRenderer.DrawLine(points[0], points[1]);
}
// Draw axis title.
AxisTitleRendererInfo atri = xari._axisTitleRendererInfo;
if (atri != null && atri.AxisTitleText != null && atri.AxisTitleText.Length > 0)
{
XRect rect = new XRect(xari.Rect.Right / 2 - atri.AxisTitleSize.Width / 2, xari.Rect.Bottom,
atri.AxisTitleSize.Width, 0);
gfx.DrawString(atri.AxisTitleText, atri.AxisTitleFont, atri.AxisTitleBrush, rect);
}
}
/// <summary>
/// Calculates the X axis describing values like minimum/maximum scale, major/minor tick and
/// major/minor tick mark width.
/// </summary>
private void CalculateXAxisValues(AxisRendererInfo rendererInfo)
{
// Calculates the maximum number of data points over all series.
SeriesCollection seriesCollection = ((Chart)rendererInfo._axis._parent)._seriesCollection;
int count = 0;
foreach (Series series in seriesCollection)
count = Math.Max(count, series.Count);
rendererInfo.MinimumScale = 0;
rendererInfo.MaximumScale = count; // At least 0
rendererInfo.MajorTick = 1;
rendererInfo.MinorTick = 0.5;
rendererInfo.MajorTickMarkWidth = DefaultMajorTickMarkWidth;
rendererInfo.MinorTickMarkWidth = DefaultMinorTickMarkWidth;
}
/// <summary>
/// Initializes the rendererInfo's xvalues. If not set by the user xvalues will be simply numbers
/// from minimum scale + 1 to maximum scale.
/// </summary>
private void InitXValues(AxisRendererInfo rendererInfo)
{
rendererInfo.XValues = ((Chart)rendererInfo._axis._parent)._xValues;
if (rendererInfo.XValues == null)
{
rendererInfo.XValues = new XValues();
XSeries xs = rendererInfo.XValues.AddXSeries();
for (double i = rendererInfo.MinimumScale + 1; i <= rendererInfo.MaximumScale; ++i)
xs.Add(i.ToString(rendererInfo.TickLabelsFormat));
}
}
/// <summary>
/// Calculates the starting and ending y position for the minor and major tick marks.
/// </summary>
private void GetTickMarkPos(AxisRendererInfo rendererInfo,
ref double majorTickMarkStart, ref double majorTickMarkEnd,
ref double minorTickMarkStart, ref double minorTickMarkEnd)
{
double majorTickMarkWidth = rendererInfo.MajorTickMarkWidth;
double minorTickMarkWidth = rendererInfo.MinorTickMarkWidth;
XRect rect = rendererInfo.Rect;
switch (rendererInfo.MajorTickMark)
{
case TickMarkType.Inside:
majorTickMarkStart = rect.Y;
majorTickMarkEnd = rect.Y - majorTickMarkWidth;
break;
case TickMarkType.Outside:
majorTickMarkStart = rect.Y;
majorTickMarkEnd = rect.Y + majorTickMarkWidth;
break;
case TickMarkType.Cross:
majorTickMarkStart = rect.Y + majorTickMarkWidth;
majorTickMarkEnd = rect.Y - majorTickMarkWidth;
break;
case TickMarkType.None:
majorTickMarkStart = 0;
majorTickMarkEnd = 0;
break;
}
switch (rendererInfo.MinorTickMark)
{
case TickMarkType.Inside:
minorTickMarkStart = rect.Y;
minorTickMarkEnd = rect.Y - minorTickMarkWidth;
break;
case TickMarkType.Outside:
minorTickMarkStart = rect.Y;
minorTickMarkEnd = rect.Y + minorTickMarkWidth;
break;
case TickMarkType.Cross:
minorTickMarkStart = rect.Y + minorTickMarkWidth;
minorTickMarkEnd = rect.Y - minorTickMarkWidth;
break;
case TickMarkType.None:
minorTickMarkStart = 0;
minorTickMarkEnd = 0;
break;
}
}
}
}

View File

@@ -0,0 +1,315 @@
#region PDFsharp Charting - A .NET charting library based on PDFsharp
//
// Authors:
// Niklas Schneider
//
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.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 System;
using PdfSharp.Drawing;
namespace PdfSharp.Charting.Renderers
{
/// <summary>
/// Represents a Y axis renderer used for charts of type Bar2D.
/// </summary>
internal class HorizontalYAxisRenderer : YAxisRenderer
{
/// <summary>
/// Initializes a new instance of the HorizontalYAxisRenderer class with the
/// specified renderer parameters.
/// </summary>
internal HorizontalYAxisRenderer(RendererParameters parms)
: base(parms)
{ }
/// <summary>
/// Returns a initialized rendererInfo based on the Y axis.
/// </summary>
internal override RendererInfo Init()
{
Chart chart = (Chart)_rendererParms.DrawingItem;
XGraphics gfx = _rendererParms.Graphics;
AxisRendererInfo yari = new AxisRendererInfo();
yari._axis = chart._yAxis;
InitScale(yari);
if (yari._axis != null)
{
ChartRendererInfo cri = (ChartRendererInfo)_rendererParms.RendererInfo;
InitTickLabels(yari, cri.DefaultFont);
InitAxisTitle(yari, cri.DefaultFont);
InitAxisLineFormat(yari);
InitGridlines(yari);
}
return yari;
}
/// <summary>
/// Calculates the space used for the Y axis.
/// </summary>
internal override void Format()
{
AxisRendererInfo yari = ((ChartRendererInfo)_rendererParms.RendererInfo).yAxisRendererInfo;
if (yari._axis != null)
{
XGraphics gfx = _rendererParms.Graphics;
XSize size = new XSize(0, 0);
// height of all ticklabels
double yMin = yari.MinimumScale;
double yMax = yari.MaximumScale;
double yMajorTick = yari.MajorTick;
double lineHeight = Double.MinValue;
XSize labelSize = new XSize(0, 0);
for (double y = yMin; y <= yMax; y += yMajorTick)
{
string str = y.ToString(yari.TickLabelsFormat);
labelSize = gfx.MeasureString(str, yari.TickLabelsFont);
size.Width += labelSize.Width;
size.Height = Math.Max(labelSize.Height, size.Height);
lineHeight = Math.Max(lineHeight, labelSize.Width);
}
// add space for tickmarks
size.Height += yari.MajorTickMarkWidth * 1.5;
// Measure axis title
XSize titleSize = new XSize(0, 0);
if (yari._axisTitleRendererInfo != null)
{
RendererParameters parms = new RendererParameters();
parms.Graphics = gfx;
parms.RendererInfo = yari;
AxisTitleRenderer atr = new AxisTitleRenderer(parms);
atr.Format();
titleSize.Height = yari._axisTitleRendererInfo.Height;
titleSize.Width = yari._axisTitleRendererInfo.Width;
}
yari.Height = size.Height + titleSize.Height;
yari.Width = Math.Max(size.Width, titleSize.Width);
yari.InnerRect = yari.Rect;
yari.LabelSize = labelSize;
}
}
/// <summary>
/// Draws the vertical Y axis.
/// </summary>
internal override void Draw()
{
AxisRendererInfo yari = ((ChartRendererInfo)_rendererParms.RendererInfo).yAxisRendererInfo;
double yMin = yari.MinimumScale;
double yMax = yari.MaximumScale;
double yMajorTick = yari.MajorTick;
double yMinorTick = yari.MinorTick;
XMatrix matrix = new XMatrix();
matrix.TranslatePrepend(-yMin, -yari.Y);
matrix.Scale(yari.InnerRect.Width / (yMax - yMin), 1, XMatrixOrder.Append);
matrix.Translate(yari.X, yari.Y, XMatrixOrder.Append);
// Draw axis.
// First draw tick marks, second draw axis.
double majorTickMarkStart = 0, majorTickMarkEnd = 0,
minorTickMarkStart = 0, minorTickMarkEnd = 0;
GetTickMarkPos(yari, ref majorTickMarkStart, ref majorTickMarkEnd, ref minorTickMarkStart, ref minorTickMarkEnd);
XGraphics gfx = _rendererParms.Graphics;
LineFormatRenderer lineFormatRenderer = new LineFormatRenderer(gfx, yari.LineFormat);
XPoint[] points = new XPoint[2];
if (yari.MinorTickMark != TickMarkType.None)
{
for (double y = yMin + yMinorTick; y < yMax; y += yMinorTick)
{
points[0].X = y;
points[0].Y = minorTickMarkStart;
points[1].X = y;
points[1].Y = minorTickMarkEnd;
matrix.TransformPoints(points);
lineFormatRenderer.DrawLine(points[0], points[1]);
}
}
XStringFormat xsf = new XStringFormat();
xsf.LineAlignment = XLineAlignment.Near;
int countTickLabels = (int)((yMax - yMin) / yMajorTick) + 1;
for (int i = 0; i < countTickLabels; ++i)
{
double y = yMin + yMajorTick * i;
string str = y.ToString(yari.TickLabelsFormat);
XSize labelSize = gfx.MeasureString(str, yari.TickLabelsFont);
if (yari.MajorTickMark != TickMarkType.None)
{
labelSize.Height += 1.5f * yari.MajorTickMarkWidth;
points[0].X = y;
points[0].Y = majorTickMarkStart;
points[1].X = y;
points[1].Y = majorTickMarkEnd;
matrix.TransformPoints(points);
lineFormatRenderer.DrawLine(points[0], points[1]);
}
XPoint[] layoutText = new XPoint[1];
layoutText[0].X = y;
layoutText[0].Y = yari.Y + 1.5 * yari.MajorTickMarkWidth;
matrix.TransformPoints(layoutText);
layoutText[0].X -= labelSize.Width / 2; // Center text vertically.
gfx.DrawString(str, yari.TickLabelsFont, yari.TickLabelsBrush, layoutText[0], xsf);
}
if (yari.LineFormat != null)
{
points[0].X = yMin;
points[0].Y = yari.Y;
points[1].X = yMax;
points[1].Y = yari.Y;
matrix.TransformPoints(points);
if (yari.MajorTickMark != TickMarkType.None)
{
// yMax is at the upper side of the axis
points[0].X -= yari.LineFormat.Width / 2;
points[1].X += yari.LineFormat.Width / 2;
}
lineFormatRenderer.DrawLine(points[0], points[1]);
}
// Draw axis title
if (yari._axisTitleRendererInfo != null)
{
RendererParameters parms = new RendererParameters();
parms.Graphics = gfx;
parms.RendererInfo = yari;
XRect rcTitle = yari.Rect;
rcTitle.Height = yari._axisTitleRendererInfo.Height;
rcTitle.Y += yari.Rect.Height - rcTitle.Height;
yari._axisTitleRendererInfo.Rect = rcTitle;
AxisTitleRenderer atr = new AxisTitleRenderer(parms);
atr.Draw();
}
}
/// <summary>
/// Calculates all values necessary for scaling the axis like minimum/maximum scale or
/// minor/major tick.
/// </summary>
private void InitScale(AxisRendererInfo rendererInfo)
{
double yMin, yMax;
CalcYAxis(out yMin, out yMax);
FineTuneYAxis(rendererInfo, yMin, yMax);
rendererInfo.MajorTickMarkWidth = DefaultMajorTickMarkWidth;
rendererInfo.MinorTickMarkWidth = DefaultMinorTickMarkWidth;
}
/// <summary>
/// Gets the top and bottom position of the major and minor tick marks depending on the
/// tick mark type.
/// </summary>
private void GetTickMarkPos(AxisRendererInfo rendererInfo,
ref double majorTickMarkStart, ref double majorTickMarkEnd,
ref double minorTickMarkStart, ref double minorTickMarkEnd)
{
double majorTickMarkWidth = rendererInfo.MajorTickMarkWidth;
double minorTickMarkWidth = rendererInfo.MinorTickMarkWidth;
double y = rendererInfo.Rect.Y;
switch (rendererInfo.MajorTickMark)
{
case TickMarkType.Inside:
majorTickMarkStart = y - majorTickMarkWidth;
majorTickMarkEnd = y;
break;
case TickMarkType.Outside:
majorTickMarkStart = y;
majorTickMarkEnd = y + majorTickMarkWidth;
break;
case TickMarkType.Cross:
majorTickMarkStart = y - majorTickMarkWidth;
majorTickMarkEnd = y + majorTickMarkWidth;
break;
//TickMarkType.None:
default:
majorTickMarkStart = 0;
majorTickMarkEnd = 0;
break;
}
switch (rendererInfo.MinorTickMark)
{
case TickMarkType.Inside:
minorTickMarkStart = y - minorTickMarkWidth;
minorTickMarkEnd = y;
break;
case TickMarkType.Outside:
minorTickMarkStart = y;
minorTickMarkEnd = y + minorTickMarkWidth;
break;
case TickMarkType.Cross:
minorTickMarkStart = y - minorTickMarkWidth;
minorTickMarkEnd = y + minorTickMarkWidth;
break;
//TickMarkType.None:
default:
minorTickMarkStart = 0;
minorTickMarkEnd = 0;
break;
}
}
/// <summary>
/// Determines the smallest and the largest number from all series of the chart.
/// </summary>
protected virtual void CalcYAxis(out double yMin, out double yMax)
{
yMin = double.MaxValue;
yMax = double.MinValue;
foreach (Series series in ((Chart)_rendererParms.DrawingItem).SeriesCollection)
{
foreach (Point point in series.Elements)
{
if (!double.IsNaN(point._value))
{
yMin = Math.Min(yMin, point.Value);
yMax = Math.Max(yMax, point.Value);
}
}
}
}
}
}

View File

@@ -0,0 +1,144 @@
#region PDFsharp Charting - A .NET charting library based on PDFsharp
//
// Authors:
// Niklas Schneider
//
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.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 System;
using PdfSharp.Drawing;
namespace PdfSharp.Charting.Renderers
{
/// <summary>
/// Represents the renderer for a legend entry.
/// </summary>
internal class LegendEntryRenderer : Renderer
{
/// <summary>
/// Initializes a new instance of the LegendEntryRenderer class with the specified renderer
/// parameters.
/// </summary>
internal LegendEntryRenderer(RendererParameters parms)
: base(parms)
{ }
/// <summary>
/// Calculates the space used by the legend entry.
/// </summary>
internal override void Format()
{
XGraphics gfx = _rendererParms.Graphics;
LegendEntryRendererInfo leri = (LegendEntryRendererInfo)_rendererParms.RendererInfo;
// Initialize
leri.MarkerArea.Width = MaxLegendMarkerWidth;
leri.MarkerArea.Height = MaxLegendMarkerHeight;
leri.MarkerSize = new XSize();
leri.MarkerSize.Width = leri.MarkerArea.Width;
leri.MarkerSize.Height = leri.MarkerArea.Height;
if (leri._seriesRendererInfo._series._chartType == ChartType.Line)
leri.MarkerArea.Width *= 3;
leri.Width = leri.MarkerArea.Width;
leri.Height = leri.MarkerArea.Height;
if (leri.EntryText != "")
{
leri.TextSize = gfx.MeasureString(leri.EntryText, leri._legendRendererInfo.Font);
if (leri._seriesRendererInfo._series._chartType == ChartType.Line)
{
leri.MarkerSize.Width = leri._seriesRendererInfo._markerRendererInfo.MarkerSize.Value;
leri.MarkerArea.Width = Math.Max(3 * leri.MarkerSize.Width, leri.MarkerArea.Width);
}
leri.MarkerArea.Height = Math.Min(leri.MarkerArea.Height, leri.TextSize.Height);
leri.MarkerSize.Height = Math.Min(leri.MarkerSize.Height, leri.TextSize.Height);
leri.Width = leri.TextSize.Width + leri.MarkerArea.Width + SpacingBetweenMarkerAndText;
leri.Height = leri.TextSize.Height;
}
}
/// <summary>
/// Draws one legend entry.
/// </summary>
internal override void Draw()
{
XGraphics gfx = _rendererParms.Graphics;
LegendEntryRendererInfo leri = (LegendEntryRendererInfo)_rendererParms.RendererInfo;
XRect rect;
if (leri._seriesRendererInfo._series._chartType == ChartType.Line)
{
// Draw line.
XPoint posLineStart = new XPoint(leri.X, leri.Y + leri.Height / 2);
XPoint posLineEnd = new XPoint(leri.X + leri.MarkerArea.Width, leri.Y + leri.Height / 2);
gfx.DrawLine(new XPen(((XSolidBrush)leri.MarkerBrush).Color), posLineStart, posLineEnd);
// Draw marker.
double x = leri.X + leri.MarkerArea.Width / 2;
XPoint posMarker = new XPoint(x, leri.Y + leri.Height / 2);
MarkerRenderer.Draw(gfx, posMarker, leri._seriesRendererInfo._markerRendererInfo);
}
else
{
// Draw series rectangle for column, bar or pie charts.
rect = new XRect(leri.X, leri.Y, leri.MarkerArea.Width, leri.MarkerArea.Height);
rect.Y += (leri.Height - leri.MarkerArea.Height) / 2;
gfx.DrawRectangle(leri.MarkerPen, leri.MarkerBrush, rect);
}
// Draw text
if (leri.EntryText.Length > 0)
{
rect = leri.Rect;
rect.X += leri.MarkerArea.Width + LegendEntryRenderer.SpacingBetweenMarkerAndText;
XStringFormat format = new XStringFormat();
format.LineAlignment = XLineAlignment.Near;
gfx.DrawString(leri.EntryText, leri._legendRendererInfo.Font,
leri._legendRendererInfo.FontColor, rect, format);
}
}
/// <summary>
/// Absolute width for markers (including line) in point.
/// </summary>
private const double MarkerWidth = 4.3; // 1.5 mm
/// <summary>
/// Maximum legend marker width in point.
/// </summary>
private const double MaxLegendMarkerWidth = 7; // 2.5 mm
/// <summary>
/// Maximum legend marker height in point.
/// </summary>
private const double MaxLegendMarkerHeight = 7; // 2.5 mm
/// <summary>
/// Insert spacing between marker and text in point.
/// </summary>
private const double SpacingBetweenMarkerAndText = 4.3; // 1.5 mm
}
}

View File

@@ -0,0 +1,179 @@
#region PDFsharp Charting - A .NET charting library based on PDFsharp
//
// Authors:
// Niklas Schneider
//
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.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 System;
using PdfSharp.Drawing;
namespace PdfSharp.Charting.Renderers
{
/// <summary>
/// Represents the legend renderer for all chart types.
/// </summary>
internal abstract class LegendRenderer : Renderer
{
/// <summary>
/// Initializes a new instance of the LegendRenderer class with the specified renderer parameters.
/// </summary>
internal LegendRenderer(RendererParameters parms)
: base(parms)
{ }
/// <summary>
/// Layouts and calculates the space used by the legend.
/// </summary>
internal override void Format()
{
ChartRendererInfo cri = (ChartRendererInfo)_rendererParms.RendererInfo;
LegendRendererInfo lri = cri.legendRendererInfo;
if (lri == null)
return;
RendererParameters parms = new RendererParameters();
parms.Graphics = _rendererParms.Graphics;
bool verticalLegend = (lri._legend._docking == DockingType.Left || lri._legend._docking == DockingType.Right);
XSize maxMarkerArea = new XSize();
LegendEntryRenderer ler = new LegendEntryRenderer(parms);
foreach (LegendEntryRendererInfo leri in lri.Entries)
{
parms.RendererInfo = leri;
ler.Format();
maxMarkerArea.Width = Math.Max(leri.MarkerArea.Width, maxMarkerArea.Width);
maxMarkerArea.Height = Math.Max(leri.MarkerArea.Height, maxMarkerArea.Height);
if (verticalLegend)
{
lri.Width = Math.Max(lri.Width, leri.Width);
lri.Height += leri.Height;
}
else
{
lri.Width += leri.Width;
lri.Height = Math.Max(lri.Height, leri.Height);
}
}
// Add padding to left, right, top and bottom
int paddingFactor = 1;
if (lri.BorderPen != null)
paddingFactor = 2;
lri.Width += (LegendRenderer.LeftPadding + LegendRenderer.RightPadding) * paddingFactor;
lri.Height += (LegendRenderer.TopPadding + LegendRenderer.BottomPadding) * paddingFactor;
if (verticalLegend)
lri.Height += LegendRenderer.EntrySpacing * (lri.Entries.Length - 1);
else
lri.Width += LegendRenderer.EntrySpacing * (lri.Entries.Length - 1);
foreach (LegendEntryRendererInfo leri in lri.Entries)
leri.MarkerArea = maxMarkerArea;
}
/// <summary>
/// Draws the legend.
/// </summary>
internal override void Draw()
{
ChartRendererInfo cri = (ChartRendererInfo)_rendererParms.RendererInfo;
LegendRendererInfo lri = cri.legendRendererInfo;
if (lri == null)
return;
XGraphics gfx = _rendererParms.Graphics;
RendererParameters parms = new RendererParameters();
parms.Graphics = gfx;
LegendEntryRenderer ler = new LegendEntryRenderer(parms);
bool verticalLegend = (lri._legend._docking == DockingType.Left || lri._legend._docking == DockingType.Right);
int paddingFactor = 1;
if (lri.BorderPen != null)
paddingFactor = 2;
XRect legendRect = lri.Rect;
legendRect.X += LegendRenderer.LeftPadding * paddingFactor;
legendRect.Y += LegendRenderer.TopPadding * paddingFactor;
foreach (LegendEntryRendererInfo leri in cri.legendRendererInfo.Entries)
{
XRect entryRect = legendRect;
entryRect.Width = leri.Width;
entryRect.Height = leri.Height;
leri.Rect = entryRect;
parms.RendererInfo = leri;
ler.Draw();
if (verticalLegend)
legendRect.Y += entryRect.Height + LegendRenderer.EntrySpacing;
else
legendRect.X += entryRect.Width + LegendRenderer.EntrySpacing;
}
// Draw border around legend
if (lri.BorderPen != null)
{
XRect borderRect = lri.Rect;
borderRect.X += LegendRenderer.LeftPadding;
borderRect.Y += LegendRenderer.TopPadding;
borderRect.Width -= LegendRenderer.LeftPadding + LegendRenderer.RightPadding;
borderRect.Height -= LegendRenderer.TopPadding + LegendRenderer.BottomPadding;
gfx.DrawRectangle(lri.BorderPen, borderRect);
}
}
/// <summary>
/// Used to insert a padding on the left.
/// </summary>
protected const double LeftPadding = 6;
/// <summary>
/// Used to insert a padding on the right.
/// </summary>
protected const double RightPadding = 6;
/// <summary>
/// Used to insert a padding at the top.
/// </summary>
protected const double TopPadding = 6;
/// <summary>
/// Used to insert a padding at the bottom.
/// </summary>
protected const double BottomPadding = 6;
/// <summary>
/// Used to insert a padding between entries.
/// </summary>
protected const double EntrySpacing = 5;
/// <summary>
/// Default line width used for the legend's border.
/// </summary>
protected const double DefaultLineWidth = 0.14; // 0.05 mm
}
}

View File

@@ -0,0 +1,196 @@
#region PDFsharp Charting - A .NET charting library based on PDFsharp
//
// Authors:
// Niklas Schneider
//
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.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 PdfSharp.Drawing;
namespace PdfSharp.Charting.Renderers
{
/// <summary>
/// Represents a line chart renderer.
/// </summary>
internal class LineChartRenderer : ColumnLikeChartRenderer
{
/// <summary>
/// Initializes a new instance of the LineChartRenderer class with the specified renderer parameters.
/// </summary>
internal LineChartRenderer(RendererParameters parms)
: base(parms)
{ }
/// <summary>
/// Returns an initialized and renderer specific rendererInfo.
/// </summary>
internal override RendererInfo Init()
{
ChartRendererInfo cri = new ChartRendererInfo();
cri._chart = (Chart)_rendererParms.DrawingItem;
_rendererParms.RendererInfo = cri;
InitSeriesRendererInfo();
LegendRenderer lr = new ColumnLikeLegendRenderer(_rendererParms);
cri.legendRendererInfo = (LegendRendererInfo)lr.Init();
AxisRenderer xar = new HorizontalXAxisRenderer(_rendererParms);
cri.xAxisRendererInfo = (AxisRendererInfo)xar.Init();
AxisRenderer yar = new VerticalYAxisRenderer(_rendererParms);
cri.yAxisRendererInfo = (AxisRendererInfo)yar.Init();
PlotArea plotArea = cri._chart.PlotArea;
LinePlotAreaRenderer lpar = new LinePlotAreaRenderer(_rendererParms);
cri.plotAreaRendererInfo = (PlotAreaRendererInfo)lpar.Init();
return cri;
}
/// <summary>
/// Layouts and calculates the space used by the line chart.
/// </summary>
internal override void Format()
{
ChartRendererInfo cri = (ChartRendererInfo)_rendererParms.RendererInfo;
LegendRenderer lr = new ColumnLikeLegendRenderer(_rendererParms);
lr.Format();
// axes
AxisRenderer xar = new HorizontalXAxisRenderer(_rendererParms);
xar.Format();
AxisRenderer yar = new VerticalYAxisRenderer(_rendererParms);
yar.Format();
// Calculate rects and positions.
CalcLayout();
// Calculated remaining plot area, now it's safe to format.
LinePlotAreaRenderer lpar = new LinePlotAreaRenderer(_rendererParms);
lpar.Format();
}
/// <summary>
/// Draws the line chart.
/// </summary>
internal override void Draw()
{
ChartRendererInfo cri = (ChartRendererInfo)_rendererParms.RendererInfo;
LegendRenderer lr = new ColumnLikeLegendRenderer(_rendererParms);
lr.Draw();
// Draw wall.
WallRenderer wr = new WallRenderer(_rendererParms);
wr.Draw();
// Draw gridlines.
GridlinesRenderer glr = new ColumnLikeGridlinesRenderer(_rendererParms);
glr.Draw();
PlotAreaBorderRenderer pabr = new PlotAreaBorderRenderer(_rendererParms);
pabr.Draw();
// Draw line chart's plot area.
LinePlotAreaRenderer lpar = new LinePlotAreaRenderer(_rendererParms);
lpar.Draw();
// Draw x- and y-axis.
if (cri.xAxisRendererInfo._axis != null)
{
AxisRenderer xar = new HorizontalXAxisRenderer(_rendererParms);
xar.Draw();
}
if (cri.yAxisRendererInfo._axis != null)
{
AxisRenderer yar = new VerticalYAxisRenderer(_rendererParms);
yar.Draw();
}
}
/// <summary>
/// Initializes all necessary data to draw a series for a line chart.
/// </summary>
private void InitSeriesRendererInfo()
{
ChartRendererInfo cri = (ChartRendererInfo)_rendererParms.RendererInfo;
SeriesCollection seriesColl = cri._chart.SeriesCollection;
cri.seriesRendererInfos = new SeriesRendererInfo[seriesColl.Count];
for (int idx = 0; idx < seriesColl.Count; ++idx)
{
SeriesRendererInfo sri = new SeriesRendererInfo();
sri._series = seriesColl[idx];
cri.seriesRendererInfos[idx] = sri;
}
InitSeries();
}
/// <summary>
/// Initializes all necessary data to draw a series for a line chart.
/// </summary>
internal void InitSeries()
{
ChartRendererInfo cri = (ChartRendererInfo)_rendererParms.RendererInfo;
int seriesIndex = 0;
foreach (SeriesRendererInfo sri in cri.seriesRendererInfos)
{
if (sri._series._markerBackgroundColor.IsEmpty)
sri.LineFormat = Converter.ToXPen(sri._series._lineFormat, LineColors.Item(seriesIndex), ChartRenderer.DefaultSeriesLineWidth);
else
sri.LineFormat = Converter.ToXPen(sri._series._lineFormat, sri._series._markerBackgroundColor, ChartRenderer.DefaultSeriesLineWidth);
sri.LineFormat.LineJoin = XLineJoin.Bevel;
MarkerRendererInfo mri = new MarkerRendererInfo();
sri._markerRendererInfo = mri;
mri.MarkerForegroundColor = sri._series._markerForegroundColor;
if (mri.MarkerForegroundColor.IsEmpty)
mri.MarkerForegroundColor = XColors.Black;
mri.MarkerBackgroundColor = sri._series._markerBackgroundColor;
if (mri.MarkerBackgroundColor.IsEmpty)
mri.MarkerBackgroundColor = sri.LineFormat.Color;
mri.MarkerSize = sri._series._markerSize;
if (mri.MarkerSize == 0)
mri.MarkerSize = 7;
if (!sri._series._markerStyleInitialized)
//mri.MarkerStyle = (MarkerStyle)(seriesIndex % (Enum.GetNames(typeof(MarkerStyle)).Length - 1) + 1);
mri.MarkerStyle = (MarkerStyle)(seriesIndex % (10 - 1) + 1);
else
mri.MarkerStyle = sri._series._markerStyle;
++seriesIndex;
}
}
}
}

View File

@@ -0,0 +1,118 @@
#region PDFsharp Charting - A .NET charting library based on PDFsharp
//
// Authors:
// Niklas Schneider
//
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.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 PdfSharp.Drawing;
namespace PdfSharp.Charting.Renderers
{
/// <summary>
/// Represents a renderer specialized to draw lines in various styles, colors and widths.
/// </summary>
class LineFormatRenderer
{
/// <summary>
/// Initializes a new instance of the LineFormatRenderer class with the specified graphics, line format
/// and default width.
/// </summary>
public LineFormatRenderer(XGraphics gfx, LineFormat lineFormat, double defaultWidth)
{
_gfx = gfx;
bool visible = false;
double width = 0;
if (lineFormat != null)
{
width = lineFormat._width;
if (width == 0 && !lineFormat.Color.IsEmpty)
width = defaultWidth;
visible = lineFormat.Visible || width > 0 || !lineFormat.Color.IsEmpty;
}
if (visible)
{
_pen = new XPen(lineFormat.Color, width);
_pen.DashStyle = lineFormat.DashStyle;
}
}
/// <summary>
/// Initializes a new instance of the LineFormatRenderer class with the specified graphics and
/// line format.
/// </summary>
public LineFormatRenderer(XGraphics gfx, LineFormat lineFormat) :
this(gfx, lineFormat, 0)
{ }
/// <summary>
/// Initializes a new instance of the LineFormatRenderer class with the specified graphics and pen.
/// </summary>
public LineFormatRenderer(XGraphics gfx, XPen pen)
{
_gfx = gfx;
_pen = pen;
}
/// <summary>
/// Draws a line from point pt0 to point pt1.
/// </summary>
public void DrawLine(XPoint pt0, XPoint pt1)
{
if (_pen != null)
_gfx.DrawLine(_pen, pt0, pt1);
}
/// <summary>
/// Draws a line specified by rect.
/// </summary>
public void DrawRectangle(XRect rect)
{
if (_pen != null)
_gfx.DrawRectangle(_pen, rect);
}
/// <summary>
/// Draws a line specified by path.
/// </summary>
public void DrawPath(XGraphicsPath path)
{
if (_pen != null)
_gfx.DrawPath(_pen, path);
}
/// <summary>
/// Surface to draw the line.
/// </summary>
readonly XGraphics _gfx;
/// <summary>
/// Pen used to draw the line.
/// </summary>
readonly XPen _pen;
}
}

View File

@@ -0,0 +1,99 @@
#region PDFsharp Charting - A .NET charting library based on PDFsharp
//
// Authors:
// Niklas Schneider
//
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.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 PdfSharp.Drawing;
namespace PdfSharp.Charting.Renderers
{
/// <summary>
/// Renders the plot area used by line charts.
/// </summary>
internal class LinePlotAreaRenderer : ColumnLikePlotAreaRenderer
{
/// <summary>
/// Initializes a new instance of the LinePlotAreaRenderer class with the
/// specified renderer parameters.
/// </summary>
internal LinePlotAreaRenderer(RendererParameters parms)
: base(parms)
{ }
/// <summary>
/// Draws the content of the line plot area.
/// </summary>
internal override void Draw()
{
ChartRendererInfo cri = (ChartRendererInfo)_rendererParms.RendererInfo;
XRect plotAreaRect = cri.plotAreaRendererInfo.Rect;
if (plotAreaRect.IsEmpty)
return;
XGraphics gfx = _rendererParms.Graphics;
XGraphicsState state = gfx.Save();
//gfx.SetClip(plotAreaRect, XCombineMode.Intersect);
gfx.IntersectClip(plotAreaRect);
//TODO Treat null values correctly.
// Points can be missing. Treat null values accordingly (NotPlotted, Interpolate etc.)
// Draw lines and markers for each data series.
XMatrix matrix = cri.plotAreaRendererInfo._matrix;
double xMajorTick = cri.xAxisRendererInfo.MajorTick;
foreach (SeriesRendererInfo sri in cri.seriesRendererInfos)
{
int count = sri._series.Elements.Count;
XPoint[] points = new XPoint[count];
for (int idx = 0; idx < count; idx++)
{
double v = sri._series.Elements[idx].Value;
if (double.IsNaN(v))
v = 0;
points[idx] = new XPoint(idx + xMajorTick / 2, v);
}
matrix.TransformPoints(points);
gfx.DrawLines(sri.LineFormat, points);
DrawMarker(gfx, points, sri);
}
//gfx.ResetClip();
gfx.Restore(state);
}
/// <summary>
/// Draws all markers given in rendererInfo at the positions specified by points.
/// </summary>
void DrawMarker(XGraphics graphics, XPoint[] points, SeriesRendererInfo rendererInfo)
{
foreach (XPoint pos in points)
MarkerRenderer.Draw(graphics, pos, rendererInfo._markerRendererInfo);
}
}
}

View File

@@ -0,0 +1,189 @@
#region PDFsharp Charting - A .NET charting library based on PDFsharp
//
// Authors:
// Niklas Schneider
//
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.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 System;
using PdfSharp.Drawing;
namespace PdfSharp.Charting.Renderers
{
/// <summary>
/// Represents a renderer for markers in line charts and legends.
/// </summary>
internal class MarkerRenderer
{
/// <summary>
/// Draws the marker given through rendererInfo at the specified position. Position specifies
/// the center of the marker.
/// </summary>
internal static void Draw(XGraphics graphics, XPoint pos, MarkerRendererInfo rendererInfo)
{
#if SILVERLIGHT
return; // BUG: Code crashs Silverlight Path class.
#pragma warning disable 0162
#endif
if (rendererInfo.MarkerStyle == MarkerStyle.None)
return;
double size = rendererInfo.MarkerSize;
double size2 = size / 2;
double x0, y0, x1, y1;
double g;
XPen foreground = new XPen(rendererInfo.MarkerForegroundColor, 0.5);
XBrush background = new XSolidBrush(rendererInfo.MarkerBackgroundColor);
XGraphicsPath gp = new XGraphicsPath();
switch (rendererInfo.MarkerStyle)
{
case MarkerStyle.Square:
x0 = pos.X - size2;
y0 = pos.Y - size2;
x1 = pos.X + size2;
y1 = pos.Y + size2;
gp.AddLine(x0, y0, x1, y0);
gp.AddLine(x1, y0, x1, y1);
gp.AddLine(x1, y1, x0, y1);
gp.AddLine(x0, y1, x0, y0);
break;
case MarkerStyle.Diamond:
gp.AddLine(x1 = pos.X + size2, pos.Y, pos.X, y0 = pos.Y - size2);
gp.AddLine(pos.X, y0, x0 = pos.X - size2, pos.Y);
gp.AddLine(x0, pos.Y, pos.X, y1 = pos.Y + size2);
gp.AddLine(pos.X, y1, x1, pos.Y);
break;
case MarkerStyle.Triangle:
y0 = pos.Y + size / 2;
y1 = pos.Y - size / 2;
g = Math.Sqrt(size * size * 4 / 3) / 2;
gp.AddLine(pos.X, y1, pos.X + g, y0);
gp.AddLine(pos.X + g, y0, pos.X - g, y0);
gp.AddLine(pos.X - g, y0, pos.X, y1);
break;
case MarkerStyle.Plus:
g = size2 / 4;
gp.AddLine(pos.X - size2, pos.Y + g, pos.X - g, pos.Y + g);
gp.AddLine(pos.X - g, pos.Y + g, pos.X - g, pos.Y + size2);
gp.AddLine(pos.X - g, pos.Y + size2, pos.X + g, pos.Y + size2);
gp.AddLine(pos.X + g, pos.Y + size2, pos.X + g, pos.Y + g);
gp.AddLine(pos.X + g, pos.Y + g, pos.X + size2, pos.Y + g);
gp.AddLine(pos.X + size2, pos.Y + g, pos.X + size2, pos.Y - g);
gp.AddLine(pos.X + size2, pos.Y - g, pos.X + g, pos.Y - g);
gp.AddLine(pos.X + g, pos.Y - g, pos.X + g, pos.Y - size2);
gp.AddLine(pos.X + g, pos.Y - size2, pos.X - g, pos.Y - size2);
gp.AddLine(pos.X - g, pos.Y - size2, pos.X - g, pos.Y - g);
gp.AddLine(pos.X - g, pos.Y - g, pos.X - size2, pos.Y - g);
gp.AddLine(pos.X - size2, pos.Y - g, pos.X - size2, pos.Y + g);
break;
case MarkerStyle.Circle:
case MarkerStyle.Dot:
x0 = pos.X - size2;
y0 = pos.Y - size2;
gp.AddEllipse(x0, y0, size, size);
break;
case MarkerStyle.Dash:
x0 = pos.X - size2;
y0 = pos.Y - size2 / 3;
x1 = pos.X + size2;
y1 = pos.Y + size2 / 3;
gp.AddLine(x0, y0, x1, y0);
gp.AddLine(x1, y0, x1, y1);
gp.AddLine(x1, y1, x0, y1);
gp.AddLine(x0, y1, x0, y0);
break;
case MarkerStyle.X:
g = size / 4;
gp.AddLine(pos.X - size2 + g, pos.Y - size2, pos.X, pos.Y - g);
gp.AddLine(pos.X, pos.Y - g, pos.X + size2 - g, pos.Y - size2);
gp.AddLine(pos.X + size2 - g, pos.Y - size2, pos.X + size2, pos.Y - size2 + g);
gp.AddLine(pos.X + size2, pos.Y - size2 + g, pos.X + g, pos.Y);
gp.AddLine(pos.X + g, pos.Y, pos.X + size2, pos.Y + size2 - g);
gp.AddLine(pos.X + size2, pos.Y + size2 - g, pos.X + size2 - g, pos.Y + size2);
gp.AddLine(pos.X + size2 - g, pos.Y + size2, pos.X, pos.Y + g);
gp.AddLine(pos.X, pos.Y + g, pos.X - size2 + g, pos.Y + size2);
gp.AddLine(pos.X - size2 + g, pos.Y + size2, pos.X - size2, pos.Y + size2 - g);
gp.AddLine(pos.X - size2, pos.Y + size2 - g, pos.X - g, pos.Y);
gp.AddLine(pos.X - g, pos.Y, pos.X - size2, pos.Y - size2 + g);
break;
case MarkerStyle.Star:
{
XPoint[] points = new XPoint[10];
double radStep = 2 * Math.PI / 5;
double outerCircle = size / 2;
double innerCircle = size / 5;
// outer circle
double rad = -(Math.PI / 2); // 90<39>
for (int idx = 0; idx < 10; idx += 2)
{
points[idx].X = pos.X + outerCircle * Math.Cos(rad);
points[idx].Y = pos.Y + outerCircle * Math.Sin(rad);
rad += radStep;
}
// inner circle
rad = -(Math.PI / 4); // 45<34>
double x = innerCircle * Math.Cos(rad);
double y = innerCircle * Math.Sin(rad);
points[1].X = pos.X + x;
points[1].Y = pos.Y + y;
points[9].X = pos.X - x;
points[9].Y = pos.Y + y;
rad += radStep;
x = innerCircle * Math.Cos(rad);
y = innerCircle * Math.Sin(rad);
points[3].X = pos.X + x;
points[3].Y = pos.Y + y;
points[7].X = pos.X - x;
points[7].Y = pos.Y + y;
rad += radStep;
y = innerCircle * Math.Sin(rad);
points[5].X = pos.X;
points[5].Y = pos.Y + y;
gp.AddLines(points);
}
break;
}
gp.CloseFigure();
if (rendererInfo.MarkerStyle != MarkerStyle.Dot)
{
graphics.DrawPath(background, gp);
graphics.DrawPath(foreground, gp);
}
}
}
}

View File

@@ -0,0 +1,177 @@
#region PDFsharp Charting - A .NET charting library based on PDFsharp
//
// Authors:
// Niklas Schneider
//
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.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 System;
using PdfSharp.Drawing;
namespace PdfSharp.Charting.Renderers
{
/// <summary>
/// Represents a pie chart renderer.
/// </summary>
internal class PieChartRenderer : ChartRenderer
{
/// <summary>
/// Initializes a new instance of the PieChartRenderer class with the
/// specified renderer parameters.
/// </summary>
internal PieChartRenderer(RendererParameters parms)
: base(parms)
{ }
/// <summary>
/// Returns an initialized and renderer specific rendererInfo.
/// </summary>
internal override RendererInfo Init()
{
ChartRendererInfo cri = new ChartRendererInfo();
cri._chart = (Chart)_rendererParms.DrawingItem;
_rendererParms.RendererInfo = cri;
InitSeries(cri);
LegendRenderer lr = new PieLegendRenderer(_rendererParms);
cri.legendRendererInfo = (LegendRendererInfo)lr.Init();
PlotArea plotArea = cri._chart.PlotArea;
PlotAreaRenderer renderer = GetPlotAreaRenderer();
cri.plotAreaRendererInfo = (PlotAreaRendererInfo)renderer.Init();
DataLabelRenderer dlr = new PieDataLabelRenderer(_rendererParms);
dlr.Init();
return cri;
}
/// <summary>
/// Layouts and calculates the space used by the pie chart.
/// </summary>
internal override void Format()
{
ChartRendererInfo cri = (ChartRendererInfo)_rendererParms.RendererInfo;
LegendRenderer lr = new PieLegendRenderer(_rendererParms);
lr.Format();
// Calculate rects and positions.
XRect chartRect = LayoutLegend();
cri.plotAreaRendererInfo.Rect = chartRect;
double edge = Math.Min(chartRect.Width, chartRect.Height);
cri.plotAreaRendererInfo.X += (chartRect.Width - edge) / 2;
cri.plotAreaRendererInfo.Y += (chartRect.Height - edge) / 2;
cri.plotAreaRendererInfo.Width = edge;
cri.plotAreaRendererInfo.Height = edge;
DataLabelRenderer dlr = new PieDataLabelRenderer(_rendererParms);
dlr.Format();
// Calculated remaining plot area, now it's safe to format.
PlotAreaRenderer renderer = GetPlotAreaRenderer();
renderer.Format();
dlr.CalcPositions();
}
/// <summary>
/// Draws the pie chart.
/// </summary>
internal override void Draw()
{
LegendRenderer lr = new PieLegendRenderer(_rendererParms);
lr.Draw();
WallRenderer wr = new WallRenderer(_rendererParms);
wr.Draw();
PlotAreaBorderRenderer pabr = new PlotAreaBorderRenderer(_rendererParms);
pabr.Draw();
PlotAreaRenderer renderer = GetPlotAreaRenderer();
renderer.Draw();
DataLabelRenderer dlr = new PieDataLabelRenderer(_rendererParms);
dlr.Draw();
}
/// <summary>
/// Returns the specific plot area renderer.
/// </summary>
private PlotAreaRenderer GetPlotAreaRenderer()
{
Chart chart = (Chart)_rendererParms.DrawingItem;
switch (chart._type)
{
case ChartType.Pie2D:
return new PieClosedPlotAreaRenderer(_rendererParms);
case ChartType.PieExploded2D:
return new PieExplodedPlotAreaRenderer(_rendererParms);
}
return null;
}
/// <summary>
/// Initializes all necessary data to draw a series for a pie chart.
/// </summary>
protected void InitSeries(ChartRendererInfo rendererInfo)
{
SeriesCollection seriesColl = rendererInfo._chart.SeriesCollection;
rendererInfo.seriesRendererInfos = new SeriesRendererInfo[seriesColl.Count];
for (int idx = 0; idx < seriesColl.Count; ++idx)
{
SeriesRendererInfo sri = new SeriesRendererInfo();
rendererInfo.seriesRendererInfos[idx] = sri;
sri._series = seriesColl[idx];
sri.LineFormat = Converter.ToXPen(sri._series._lineFormat, XColors.Black, ChartRenderer.DefaultSeriesLineWidth);
sri.FillFormat = Converter.ToXBrush(sri._series._fillFormat, ColumnColors.Item(idx));
sri._pointRendererInfos = new SectorRendererInfo[sri._series._seriesElements.Count];
for (int pointIdx = 0; pointIdx < sri._pointRendererInfos.Length; ++pointIdx)
{
PointRendererInfo pri = new SectorRendererInfo();
Point point = sri._series._seriesElements[pointIdx];
pri.Point = point;
if (point != null)
{
pri.LineFormat = sri.LineFormat;
if (point._lineFormat != null && !point._lineFormat._color.IsEmpty)
pri.LineFormat = new XPen(point._lineFormat._color);
if (point._fillFormat != null && !point._fillFormat._color.IsEmpty)
pri.FillFormat = new XSolidBrush(point._fillFormat._color);
else
pri.FillFormat = new XSolidBrush(PieColors.Item(pointIdx));
pri.LineFormat.LineJoin = XLineJoin.Round;
}
sri._pointRendererInfos[pointIdx] = pri;
}
}
}
}
}

View File

@@ -0,0 +1,103 @@
#region PDFsharp Charting - A .NET charting library based on PDFsharp
//
// Authors:
// Niklas Schneider
//
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.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 System;
using PdfSharp.Drawing;
namespace PdfSharp.Charting.Renderers
{
/// <summary>
/// Represents a closed pie plot area renderer.
/// </summary>
internal class PieClosedPlotAreaRenderer : PiePlotAreaRenderer
{
/// <summary>
/// Initializes a new instance of the PiePlotAreaRenderer class
/// with the specified renderer parameters.
/// </summary>
internal PieClosedPlotAreaRenderer(RendererParameters parms)
: base(parms)
{ }
/// <summary>
/// Calculate angles for each sector.
/// </summary>
protected override void CalcSectors()
{
ChartRendererInfo cri = (ChartRendererInfo)_rendererParms.RendererInfo;
if (cri.seriesRendererInfos.Length == 0)
return;
SeriesRendererInfo sri = cri.seriesRendererInfos[0];
double sumValues = sri.SumOfPoints;
if (sumValues == 0)
return;
double textMeasure = 0;
if (sri._dataLabelRendererInfo != null && sri._dataLabelRendererInfo.Position == DataLabelPosition.OutsideEnd)
{
foreach (DataLabelEntryRendererInfo dleri in sri._dataLabelRendererInfo.Entries)
{
textMeasure = Math.Max(textMeasure, dleri.Width);
textMeasure = Math.Max(textMeasure, dleri.Height);
}
}
XRect pieRect = cri.plotAreaRendererInfo.Rect;
if (textMeasure != 0)
{
pieRect.X += textMeasure;
pieRect.Y += textMeasure;
pieRect.Width -= 2 * textMeasure;
pieRect.Height -= 2 * textMeasure;
}
double startAngle = 270, sweepAngle = 0;
foreach (SectorRendererInfo sector in sri._pointRendererInfos)
{
if (!double.IsNaN(sector.Point._value) && sector.Point._value != 0)
{
sweepAngle = 360 / (sumValues / Math.Abs(sector.Point._value));
sector.Rect = pieRect;
sector.StartAngle = startAngle;
sector.SweepAngle = sweepAngle;
startAngle += sweepAngle;
}
else
{
sector.StartAngle = double.NaN;
sector.SweepAngle = double.NaN;
}
}
}
}
}

View File

@@ -0,0 +1,182 @@
#region PDFsharp Charting - A .NET charting library based on PDFsharp
//
// Authors:
// Niklas Schneider
//
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.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 System;
using PdfSharp.Drawing;
namespace PdfSharp.Charting.Renderers
{
/// <summary>
/// Represents a data label renderer for pie charts.
/// </summary>
internal class PieDataLabelRenderer : DataLabelRenderer
{
/// <summary>
/// Initializes a new instance of the PieDataLabelRenderer class with the
/// specified renderer parameters.
/// </summary>
internal PieDataLabelRenderer(RendererParameters parms)
: base(parms)
{ }
/// <summary>
/// Calculates the space used by the data labels.
/// </summary>
internal override void Format()
{
ChartRendererInfo cri = (ChartRendererInfo)_rendererParms.RendererInfo;
if (cri.seriesRendererInfos.Length == 0)
return;
SeriesRendererInfo sri = cri.seriesRendererInfos[0];
if (sri._dataLabelRendererInfo == null)
return;
double sumValues = sri.SumOfPoints;
XGraphics gfx = _rendererParms.Graphics;
sri._dataLabelRendererInfo.Entries = new DataLabelEntryRendererInfo[sri._pointRendererInfos.Length];
int index = 0;
foreach (SectorRendererInfo sector in sri._pointRendererInfos)
{
DataLabelEntryRendererInfo dleri = new DataLabelEntryRendererInfo();
if (sri._dataLabelRendererInfo.Type != DataLabelType.None)
{
if (sri._dataLabelRendererInfo.Type == DataLabelType.Percent)
{
double percent = 100 / (sumValues / Math.Abs(sector.Point._value));
dleri.Text = percent.ToString(sri._dataLabelRendererInfo.Format) + "%";
}
else if (sri._dataLabelRendererInfo.Type == DataLabelType.Value)
dleri.Text = sector.Point._value.ToString(sri._dataLabelRendererInfo.Format);
if (dleri.Text.Length > 0)
dleri.Size = gfx.MeasureString(dleri.Text, sri._dataLabelRendererInfo.Font);
}
sri._dataLabelRendererInfo.Entries[index++] = dleri;
}
}
/// <summary>
/// Draws the data labels of the pie chart.
/// </summary>
internal override void Draw()
{
ChartRendererInfo cri = (ChartRendererInfo)_rendererParms.RendererInfo;
if (cri.seriesRendererInfos.Length == 0)
return;
SeriesRendererInfo sri = cri.seriesRendererInfos[0];
if (sri == null || sri._dataLabelRendererInfo == null)
return;
XGraphics gfx = _rendererParms.Graphics;
XFont font = sri._dataLabelRendererInfo.Font;
XBrush fontColor = sri._dataLabelRendererInfo.FontColor;
XStringFormat format = XStringFormats.Center;
format.LineAlignment = XLineAlignment.Center;
foreach (DataLabelEntryRendererInfo dataLabel in sri._dataLabelRendererInfo.Entries)
{
if (dataLabel.Text != null)
gfx.DrawString(dataLabel.Text, font, fontColor, dataLabel.Rect, format);
}
}
/// <summary>
/// Calculates the data label positions specific for pie charts.
/// </summary>
internal override void CalcPositions()
{
ChartRendererInfo cri = (ChartRendererInfo)_rendererParms.RendererInfo;
XGraphics gfx = _rendererParms.Graphics;
if (cri.seriesRendererInfos.Length > 0)
{
SeriesRendererInfo sri = cri.seriesRendererInfos[0];
if (sri != null && sri._dataLabelRendererInfo != null)
{
int sectorIndex = 0;
foreach (SectorRendererInfo sector in sri._pointRendererInfos)
{
// Determine output rectangle
double midAngle = sector.StartAngle + sector.SweepAngle / 2;
double radMidAngle = midAngle / 180 * Math.PI;
XPoint origin = new XPoint(sector.Rect.X + sector.Rect.Width / 2,
sector.Rect.Y + sector.Rect.Height / 2);
double radius = sector.Rect.Width / 2;
double halfradius = radius / 2;
DataLabelEntryRendererInfo dleri = sri._dataLabelRendererInfo.Entries[sectorIndex++];
switch (sri._dataLabelRendererInfo.Position)
{
case DataLabelPosition.OutsideEnd:
// Outer border of the circle.
dleri.X = origin.X + (radius * Math.Cos(radMidAngle));
dleri.Y = origin.Y + (radius * Math.Sin(radMidAngle));
if (dleri.X < origin.X)
dleri.X -= dleri.Width;
if (dleri.Y < origin.Y)
dleri.Y -= dleri.Height;
break;
case DataLabelPosition.InsideEnd:
// Inner border of the circle.
dleri.X = origin.X + (radius * Math.Cos(radMidAngle));
dleri.Y = origin.Y + (radius * Math.Sin(radMidAngle));
if (dleri.X > origin.X)
dleri.X -= dleri.Width;
if (dleri.Y > origin.Y)
dleri.Y -= dleri.Height;
break;
case DataLabelPosition.Center:
// Centered
dleri.X = origin.X + (halfradius * Math.Cos(radMidAngle));
dleri.Y = origin.Y + (halfradius * Math.Sin(radMidAngle));
dleri.X -= dleri.Width / 2;
dleri.Y -= dleri.Height / 2;
break;
case DataLabelPosition.InsideBase:
// Aligned at the base/center of the circle
dleri.X = origin.X;
dleri.Y = origin.Y;
if (dleri.X < origin.X)
dleri.X -= dleri.Width;
if (dleri.Y < origin.Y)
dleri.Y -= dleri.Height;
break;
}
}
}
}
}
}
}

View File

@@ -0,0 +1,122 @@
#region PDFsharp Charting - A .NET charting library based on PDFsharp
//
// Authors:
// Niklas Schneider
//
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.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 System;
using PdfSharp.Drawing;
namespace PdfSharp.Charting.Renderers
{
/// <summary>
/// Represents a exploded pie plot area renderer.
/// </summary>
internal class PieExplodedPlotAreaRenderer : PiePlotAreaRenderer
{
/// <summary>
/// Initializes a new instance of the PieExplodedPlotAreaRenderer class
/// with the specified renderer parameters.
/// </summary>
internal PieExplodedPlotAreaRenderer(RendererParameters parms)
: base(parms)
{ }
/// <summary>
/// Calculate angles for each sector.
/// </summary>
protected override void CalcSectors()
{
ChartRendererInfo cri = (ChartRendererInfo)_rendererParms.RendererInfo;
if (cri.seriesRendererInfos.Length == 0)
return;
SeriesRendererInfo sri = cri.seriesRendererInfos[0];
double sumValues = sri.SumOfPoints;
if (sumValues == 0)
return;
double textMeasure = 0;
if (sri._dataLabelRendererInfo != null && sri._dataLabelRendererInfo.Position == DataLabelPosition.OutsideEnd)
{
foreach (DataLabelEntryRendererInfo dleri in sri._dataLabelRendererInfo.Entries)
{
textMeasure = Math.Max(textMeasure, dleri.Width);
textMeasure = Math.Max(textMeasure, dleri.Height);
}
}
XRect pieRect = cri.plotAreaRendererInfo.Rect;
if (textMeasure != 0)
{
pieRect.X += textMeasure;
pieRect.Y += textMeasure;
pieRect.Width -= 2 * textMeasure;
pieRect.Height -= 2 * textMeasure;
}
XPoint origin = new XPoint(pieRect.X + pieRect.Width / 2, pieRect.Y + pieRect.Height / 2);
XRect innerRect = new XRect();
XPoint p1 = new XPoint();
double midAngle = 0, sectorStartAngle = 0, sectorSweepAngle = 0,
deltaAngle = 2, startAngle = 270, sweepAngle = 0,
rInnerCircle = pieRect.Width / 15,
rOuterCircle = pieRect.Width / 2;
foreach (SectorRendererInfo sector in sri._pointRendererInfos)
{
if (!double.IsNaN(sector.Point._value) && sector.Point._value != 0)
{
sweepAngle = 360 / (sumValues / Math.Abs(sector.Point._value));
midAngle = startAngle + sweepAngle / 2;
sectorStartAngle = Math.Max(0, startAngle + deltaAngle);
sectorSweepAngle = Math.Max(sweepAngle, sweepAngle - deltaAngle);
p1.X = origin.X + rInnerCircle * Math.Cos(midAngle / 180 * Math.PI);
p1.Y = origin.Y + rInnerCircle * Math.Sin(midAngle / 180 * Math.PI);
innerRect.X = p1.X - rOuterCircle + rInnerCircle;
innerRect.Y = p1.Y - rOuterCircle + rInnerCircle;
innerRect.Width = (rOuterCircle - rInnerCircle) * 2;
innerRect.Height = innerRect.Width;
sector.Rect = innerRect;
sector.StartAngle = sectorStartAngle;
sector.SweepAngle = sectorSweepAngle;
startAngle += sweepAngle;
}
else
{
sector.StartAngle = double.NaN;
sector.SweepAngle = double.NaN;
}
}
}
}
}

View File

@@ -0,0 +1,95 @@
#region PDFsharp Charting - A .NET charting library based on PDFsharp
//
// Authors:
// Niklas Schneider
//
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.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 PdfSharp.Drawing;
namespace PdfSharp.Charting.Renderers
{
/// <summary>
/// Represents the legend renderer specific to pie charts.
/// </summary>
internal class PieLegendRenderer : LegendRenderer
{
/// <summary>
/// Initializes a new instance of the PieLegendRenderer class with the specified renderer
/// parameters.
/// </summary>
internal PieLegendRenderer(RendererParameters parms)
: base(parms)
{ }
/// <summary>
/// Initializes the legend's renderer info. Each data point will be represented through
/// a legend entry renderer info.
/// </summary>
internal override RendererInfo Init()
{
LegendRendererInfo lri = null;
ChartRendererInfo cri = (ChartRendererInfo)_rendererParms.RendererInfo;
if (cri._chart._legend != null)
{
lri = new LegendRendererInfo();
lri._legend = cri._chart._legend;
lri.Font = Converter.ToXFont(lri._legend._font, cri.DefaultFont);
lri.FontColor = new XSolidBrush(XColors.Black);
if (lri._legend._lineFormat != null)
lri.BorderPen = Converter.ToXPen(lri._legend._lineFormat, XColors.Black, DefaultLineWidth, XDashStyle.Solid);
XSeries xseries = null;
if (cri._chart._xValues != null)
xseries = cri._chart._xValues[0];
int index = 0;
SeriesRendererInfo sri = cri.seriesRendererInfos[0];
lri.Entries = new LegendEntryRendererInfo[sri._pointRendererInfos.Length];
foreach (PointRendererInfo pri in sri._pointRendererInfos)
{
LegendEntryRendererInfo leri = new LegendEntryRendererInfo();
leri._seriesRendererInfo = sri;
leri._legendRendererInfo = lri;
leri.EntryText = string.Empty;
if (xseries != null)
{
if (xseries.Count > index)
leri.EntryText = xseries[index]._value;
}
else
leri.EntryText = (index + 1).ToString(); // create default/dummy entry
leri.MarkerPen = pri.LineFormat;
leri.MarkerBrush = pri.FillFormat;
lri.Entries[index++] = leri;
}
}
return lri;
}
}
}

View File

@@ -0,0 +1,94 @@
#region PDFsharp Charting - A .NET charting library based on PDFsharp
//
// Authors:
// Niklas Schneider
//
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.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 PdfSharp.Drawing;
namespace PdfSharp.Charting.Renderers
{
/// <summary>
/// Represents the base for all pie plot area renderer.
/// </summary>
internal abstract class PiePlotAreaRenderer : PlotAreaRenderer
{
/// <summary>
/// Initializes a new instance of the PiePlotAreaRenderer class
/// with the specified renderer parameters.
/// </summary>
internal PiePlotAreaRenderer(RendererParameters parms)
: base(parms)
{ }
/// <summary>
/// Layouts and calculates the space used by the pie plot area.
/// </summary>
internal override void Format()
{
CalcSectors();
}
/// <summary>
/// Draws the content of the pie plot area.
/// </summary>
internal override void Draw()
{
ChartRendererInfo cri = (ChartRendererInfo)_rendererParms.RendererInfo;
XRect plotAreaRect = cri.plotAreaRendererInfo.Rect;
if (plotAreaRect.IsEmpty)
return;
if (cri.seriesRendererInfos.Length == 0)
return;
XGraphics gfx = _rendererParms.Graphics;
XGraphicsState state = gfx.Save();
// Draw sectors.
SeriesRendererInfo sri = cri.seriesRendererInfos[0];
foreach (SectorRendererInfo sector in sri._pointRendererInfos)
{
if (!double.IsNaN(sector.StartAngle) && !double.IsNaN(sector.SweepAngle))
gfx.DrawPie(sector.FillFormat, sector.Rect, sector.StartAngle, sector.SweepAngle);
}
// Draw border of the sectors.
foreach (SectorRendererInfo sector in sri._pointRendererInfos)
{
if (!double.IsNaN(sector.StartAngle) && !double.IsNaN(sector.SweepAngle))
gfx.DrawPie(sector.LineFormat, sector.Rect, sector.StartAngle, sector.SweepAngle);
}
gfx.Restore(state);
}
/// <summary>
/// Calculates the specific positions for each sector.
/// </summary>
protected abstract void CalcSectors();
}
}

View File

@@ -0,0 +1,61 @@
#region PDFsharp Charting - A .NET charting library based on PDFsharp
//
// Authors:
// Niklas Schneider
//
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.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 PdfSharp.Drawing;
namespace PdfSharp.Charting.Renderers
{
/// <summary>
/// Represents the border renderer for plot areas.
/// </summary>
internal class PlotAreaBorderRenderer : Renderer
{
/// <summary>
/// Initializes a new instance of the PlotAreaBorderRenderer class with the specified
/// renderer parameters.
/// </summary>
internal PlotAreaBorderRenderer(RendererParameters parms)
: base(parms)
{ }
/// <summary>
/// Draws the border around the plot area.
/// </summary>
internal override void Draw()
{
ChartRendererInfo cri = (ChartRendererInfo)_rendererParms.RendererInfo;
if (cri.plotAreaRendererInfo.LineFormat != null && cri.plotAreaRendererInfo.LineFormat.Width > 0)
{
XGraphics gfx = _rendererParms.Graphics;
LineFormatRenderer lineFormatRenderer = new LineFormatRenderer(gfx, cri.plotAreaRendererInfo.LineFormat);
lineFormatRenderer.DrawRectangle(cri.plotAreaRendererInfo.Rect);
}
}
}
}

View File

@@ -0,0 +1,83 @@
#region PDFsharp Charting - A .NET charting library based on PDFsharp
//
// Authors:
// Niklas Schneider
//
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.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 PdfSharp.Drawing;
namespace PdfSharp.Charting.Renderers
{
/// <summary>
/// Base class for all plot area renderers.
/// </summary>
internal abstract class PlotAreaRenderer : Renderer
{
/// <summary>
/// Initializes a new instance of the PlotAreaRenderer class with the specified renderer parameters.
/// </summary>
internal PlotAreaRenderer(RendererParameters parms)
: base(parms)
{ }
/// <summary>
/// Returns an initialized PlotAreaRendererInfo.
/// </summary>
internal override RendererInfo Init()
{
PlotAreaRendererInfo pari = new PlotAreaRendererInfo();
pari._plotArea = ((ChartRendererInfo)_rendererParms.RendererInfo)._chart._plotArea;
InitLineFormat(pari);
InitFillFormat(pari);
return pari;
}
/// <summary>
/// Initializes the plot area's line format common to all derived plot area renderers.
/// If line format is given all uninitialized values will be set.
/// </summary>
protected void InitLineFormat(PlotAreaRendererInfo rendererInfo)
{
if (rendererInfo._plotArea._lineFormat != null)
rendererInfo.LineFormat = Converter.ToXPen(rendererInfo._plotArea._lineFormat, XColors.Black, DefaultLineWidth);
}
/// <summary>
/// Initializes the plot area's fill format common to all derived plot area renderers.
/// If fill format is given all uninitialized values will be set.
/// </summary>
protected void InitFillFormat(PlotAreaRendererInfo rendererInfo)
{
if (rendererInfo._plotArea._fillFormat != null)
rendererInfo.FillFormat = Converter.ToXBrush(rendererInfo._plotArea._fillFormat, XColors.White);
}
/// <summary>
/// Represents the default line width for the plot area's border.
/// </summary>
protected const double DefaultLineWidth = 0.15;
}
}

View File

@@ -0,0 +1,72 @@
#region PDFsharp Charting - A .NET charting library based on PDFsharp
//
// Authors:
// Niklas Schneider
//
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.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
namespace PdfSharp.Charting.Renderers
{
/// <summary>
/// Base class of all renderers.
/// </summary>
internal abstract class Renderer
{
/// <summary>
/// Initializes a new instance of the Renderer class with the specified renderer parameters.
/// </summary>
internal Renderer(RendererParameters rendererParms)
{
_rendererParms = rendererParms;
}
/// <summary>
/// Derived renderer should return an initialized and renderer specific rendererInfo,
/// e. g. XAxisRenderer returns an new instance of AxisRendererInfo class.
/// </summary>
internal virtual RendererInfo Init()
{
return null;
}
/// <summary>
/// Layouts and calculates the space used by the renderer's drawing item.
/// </summary>
internal virtual void Format()
{
// nothing to do
}
/// <summary>
/// Draws the item.
/// </summary>
internal abstract void Draw();
/// <summary>
/// Holds all necessary rendering information.
/// </summary>
protected RendererParameters _rendererParms;
}
}

View File

@@ -0,0 +1,409 @@
#region PDFsharp Charting - A .NET charting library based on PDFsharp
//
// Authors:
// Niklas Schneider
//
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.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 System;
using PdfSharp.Drawing;
namespace PdfSharp.Charting.Renderers
{
/// <summary>
/// Represents the base class of all renderer infos.
/// Renderer infos are used to hold all necessary information and time consuming calculations
/// between rendering cycles.
/// </summary>
internal abstract class RendererInfo
{ }
/// <summary>
/// Base class for all renderer infos which defines an area.
/// </summary>
internal abstract class AreaRendererInfo : RendererInfo
{
/// <summary>
/// Gets or sets the x coordinate of this rectangle.
/// </summary>
internal virtual double X
{
get { return _rect.X; }
set { _rect.X = value; }
}
/// <summary>
/// Gets or sets the y coordinate of this rectangle.
/// </summary>
internal virtual double Y
{
get { return _rect.Y; }
set { _rect.Y = value; }
}
/// <summary>
/// Gets or sets the width of this rectangle.
/// </summary>
internal virtual double Width
{
get { return _rect.Width; }
set { _rect.Width = value; }
}
/// <summary>
/// Gets or sets the height of this rectangle.
/// </summary>
internal virtual double Height
{
get { return _rect.Height; }
set { _rect.Height = value; }
}
/// <summary>
/// Gets the area's size.
/// </summary>
internal XSize Size
{
get { return _rect.Size; }
set { _rect.Size = value; }
}
/// <summary>
/// Gets the area's rectangle.
/// </summary>
internal XRect Rect
{
get { return _rect; }
set { _rect = value; }
}
XRect _rect;
}
/// <summary>
/// A ChartRendererInfo stores information of all main parts of a chart like axis renderer info or
/// plotarea renderer info.
/// </summary>
internal class ChartRendererInfo : AreaRendererInfo
{
internal Chart _chart;
internal AxisRendererInfo xAxisRendererInfo;
internal AxisRendererInfo yAxisRendererInfo;
//internal AxisRendererInfo zAxisRendererInfo; // not yet used
internal PlotAreaRendererInfo plotAreaRendererInfo;
internal LegendRendererInfo legendRendererInfo;
internal SeriesRendererInfo[] seriesRendererInfos;
/// <summary>
/// Gets the chart's default font for rendering.
/// </summary>
internal XFont DefaultFont
{
get
{
return _defaultFont ??
(_defaultFont = Converter.ToXFont(_chart._font, new XFont("Arial", 12, XFontStyle.Regular)));
}
}
XFont _defaultFont;
/// <summary>
/// Gets the chart's default font for rendering data labels.
/// </summary>
internal XFont DefaultDataLabelFont
{
get
{
return _defaultDataLabelFont ??
(_defaultDataLabelFont = Converter.ToXFont(_chart._font, new XFont("Arial", 10, XFontStyle.Regular)));
}
}
XFont _defaultDataLabelFont;
}
/// <summary>
/// A CombinationRendererInfo stores information for rendering combination of charts.
/// </summary>
internal class CombinationRendererInfo : ChartRendererInfo
{
internal SeriesRendererInfo[] _commonSeriesRendererInfos;
internal SeriesRendererInfo[] _areaSeriesRendererInfos;
internal SeriesRendererInfo[] _columnSeriesRendererInfos;
internal SeriesRendererInfo[] _lineSeriesRendererInfos;
}
/// <summary>
/// PointRendererInfo is used to render one single data point which is part of a data series.
/// </summary>
internal class PointRendererInfo : RendererInfo
{
internal Point Point;
internal XPen LineFormat;
internal XBrush FillFormat;
}
/// <summary>
/// Represents one sector of a series used by a pie chart.
/// </summary>
internal class SectorRendererInfo : PointRendererInfo
{
internal XRect Rect;
internal double StartAngle;
internal double SweepAngle;
}
/// <summary>
/// Represents one data point of a series and the corresponding rectangle.
/// </summary>
internal class ColumnRendererInfo : PointRendererInfo
{
internal XRect Rect;
}
/// <summary>
/// Stores rendering specific information for one data label entry.
/// </summary>
internal class DataLabelEntryRendererInfo : AreaRendererInfo
{
internal string Text;
}
/// <summary>
/// Stores data label specific rendering information.
/// </summary>
internal class DataLabelRendererInfo : RendererInfo
{
internal DataLabelEntryRendererInfo[] Entries;
internal string Format;
internal XFont Font;
internal XBrush FontColor;
internal DataLabelPosition Position;
internal DataLabelType Type;
}
/// <summary>
/// SeriesRendererInfo holds all data series specific rendering information.
/// </summary>
internal class SeriesRendererInfo : RendererInfo
{
internal Series _series;
internal DataLabelRendererInfo _dataLabelRendererInfo;
internal PointRendererInfo[] _pointRendererInfos;
internal XPen LineFormat;
internal XBrush FillFormat;
// Used if ChartType is set to Line
internal MarkerRendererInfo _markerRendererInfo;
/// <summary>
/// Gets the sum of all points in PointRendererInfo.
/// </summary>
internal double SumOfPoints
{
get
{
double sum = 0;
foreach (PointRendererInfo pri in _pointRendererInfos)
{
if (!double.IsNaN(pri.Point._value))
sum += Math.Abs(pri.Point._value);
}
return sum;
}
}
}
/// <summary>
/// Represents a description of a marker for a line chart.
/// </summary>
internal class MarkerRendererInfo : RendererInfo
{
internal XUnit MarkerSize;
internal MarkerStyle MarkerStyle;
internal XColor MarkerForegroundColor;
internal XColor MarkerBackgroundColor;
}
/// <summary>
/// An AxisRendererInfo holds all axis specific rendering information.
/// </summary>
internal class AxisRendererInfo : AreaRendererInfo
{
internal Axis _axis;
internal double MinimumScale;
internal double MaximumScale;
internal double MajorTick;
internal double MinorTick;
internal TickMarkType MinorTickMark;
internal TickMarkType MajorTickMark;
internal double MajorTickMarkWidth;
internal double MinorTickMarkWidth;
internal XPen MajorTickMarkLineFormat;
internal XPen MinorTickMarkLineFormat;
//Gridlines
internal XPen MajorGridlinesLineFormat;
internal XPen MinorGridlinesLineFormat;
//AxisTitle
internal AxisTitleRendererInfo _axisTitleRendererInfo;
//TickLabels
internal string TickLabelsFormat;
internal XFont TickLabelsFont;
internal XBrush TickLabelsBrush;
internal double TickLabelsHeight;
//LineFormat
internal XPen LineFormat;
//Chart.XValues, used for X axis only.
internal XValues XValues;
/// <summary>
/// Sets the x coordinate of the inner rectangle.
/// </summary>
internal override double X
{
set
{
base.X = value;
InnerRect.X = value;
}
}
/// <summary>
/// Sets the y coordinate of the inner rectangle.
/// </summary>
internal override double Y
{
set
{
base.Y = value;
InnerRect.Y = value + LabelSize.Height / 2;
}
}
/// <summary>
/// Sets the height of the inner rectangle.
/// </summary>
internal override double Height
{
set
{
base.Height = value;
InnerRect.Height = value - (InnerRect.Y - Y);
}
}
/// <summary>
/// Sets the width of the inner rectangle.
/// </summary>
internal override double Width
{
set
{
base.Width = value;
InnerRect.Width = value - LabelSize.Width / 2;
}
}
internal XRect InnerRect;
internal XSize LabelSize;
}
internal class AxisTitleRendererInfo : AreaRendererInfo
{
internal AxisTitle _axisTitle;
internal string AxisTitleText;
internal XFont AxisTitleFont;
internal XBrush AxisTitleBrush;
internal double AxisTitleOrientation;
internal HorizontalAlignment AxisTitleAlignment;
internal VerticalAlignment AxisTitleVerticalAlignment;
internal XSize AxisTitleSize;
}
/// <summary>
/// Represents one description of a legend entry.
/// </summary>
internal class LegendEntryRendererInfo : AreaRendererInfo
{
internal SeriesRendererInfo _seriesRendererInfo;
internal LegendRendererInfo _legendRendererInfo;
internal string EntryText;
/// <summary>
/// Size for the marker only.
/// </summary>
internal XSize MarkerSize;
internal XPen MarkerPen;
internal XBrush MarkerBrush;
/// <summary>
/// Width for marker area. Extra spacing for line charts are considered.
/// </summary>
internal XSize MarkerArea;
/// <summary>
/// Size for text area.
/// </summary>
internal XSize TextSize;
}
/// <summary>
/// Stores legend specific rendering information.
/// </summary>
internal class LegendRendererInfo : AreaRendererInfo
{
internal Legend _legend;
internal XFont Font;
internal XBrush FontColor;
internal XPen BorderPen;
internal LegendEntryRendererInfo[] Entries;
}
/// <summary>
/// Stores rendering information common to all plot area renderers.
/// </summary>
internal class PlotAreaRendererInfo : AreaRendererInfo
{
internal PlotArea _plotArea;
/// <summary>
/// Saves the plot area's matrix.
/// </summary>
internal XMatrix _matrix;
internal XPen LineFormat;
internal XBrush FillFormat;
}
}

View File

@@ -0,0 +1,105 @@
#region PDFsharp Charting - A .NET charting library based on PDFsharp
//
// Authors:
// Niklas Schneider
//
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.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 PdfSharp.Drawing;
namespace PdfSharp.Charting.Renderers
{
/// <summary>
/// Represents the necessary data for chart rendering.
/// </summary>
internal class RendererParameters
{
/// <summary>
/// Initializes a new instance of the RendererParameters class.
/// </summary>
public RendererParameters()
{ }
/// <summary>
/// Initializes a new instance of the RendererParameters class with the specified graphics and
/// coordinates.
/// </summary>
public RendererParameters(XGraphics gfx, double x, double y, double width, double height)
{
_gfx = gfx;
_box = new XRect(x, y, width, height);
}
/// <summary>
/// Initializes a new instance of the RendererParameters class with the specified graphics and
/// rectangle.
/// </summary>
public RendererParameters(XGraphics gfx, XRect boundingBox)
{
_gfx = gfx;
_box = boundingBox;
}
/// <summary>
/// Gets or sets the graphics object.
/// </summary>
public XGraphics Graphics
{
get { return _gfx; }
set { _gfx = value; }
}
XGraphics _gfx;
/// <summary>
/// Gets or sets the item to draw.
/// </summary>
public object DrawingItem
{
get { return _item; }
set { _item = value; }
}
object _item;
/// <summary>
/// Gets or sets the rectangle for the drawing item.
/// </summary>
public XRect Box
{
get { return _box; }
set { _box = value; }
}
XRect _box;
/// <summary>
/// Gets or sets the RendererInfo.
/// </summary>
public RendererInfo RendererInfo
{
get { return _rendererInfo; }
set { _rendererInfo = value; }
}
RendererInfo _rendererInfo;
}
}

View File

@@ -0,0 +1,84 @@
#region PDFsharp Charting - A .NET charting library based on PDFsharp
//
// Authors:
// Niklas Schneider
//
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.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 System;
namespace PdfSharp.Charting.Renderers
{
/// <summary>
/// Represents a Y axis renderer used for charts of type Column2D or Line.
/// </summary>
internal class VerticalStackedYAxisRenderer : VerticalYAxisRenderer
{
/// <summary>
/// Initializes a new instance of the VerticalYAxisRenderer class with the
/// specified renderer parameters.
/// </summary>
internal VerticalStackedYAxisRenderer(RendererParameters parms)
: base(parms)
{ }
/// <summary>
/// Determines the sum of the smallest and the largest stacked column
/// from all series of the chart.
/// </summary>
protected override void CalcYAxis(out double yMin, out double yMax)
{
yMin = double.MaxValue;
yMax = double.MinValue;
ChartRendererInfo cri = (ChartRendererInfo)_rendererParms.RendererInfo;
int maxPoints = 0;
foreach (SeriesRendererInfo sri in cri.seriesRendererInfos)
maxPoints = Math.Max(maxPoints, sri._series._seriesElements.Count);
for (int pointIdx = 0; pointIdx < maxPoints; ++pointIdx)
{
double valueSumPos = 0, valueSumNeg = 0;
foreach (SeriesRendererInfo sri in cri.seriesRendererInfos)
{
if (sri._pointRendererInfos.Length <= pointIdx)
break;
ColumnRendererInfo column = (ColumnRendererInfo)sri._pointRendererInfos[pointIdx];
if (column.Point != null && !double.IsNaN(column.Point._value))
{
if (column.Point._value < 0)
valueSumNeg += column.Point._value;
else
valueSumPos += column.Point._value;
}
}
yMin = Math.Min(valueSumNeg, yMin);
yMax = Math.Max(valueSumPos, yMax);
}
}
}
}

View File

@@ -0,0 +1,296 @@
#region PDFsharp Charting - A .NET charting library based on PDFsharp
//
// Authors:
// Niklas Schneider
//
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.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 System;
using PdfSharp.Drawing;
namespace PdfSharp.Charting.Renderers
{
/// <summary>
/// Represents an axis renderer used for charts of type Bar2D.
/// </summary>
internal class VerticalXAxisRenderer : XAxisRenderer
{
/// <summary>
/// Initializes a new instance of the VerticalXAxisRenderer class with the specified renderer parameters.
/// </summary>
internal VerticalXAxisRenderer(RendererParameters parms)
: base(parms)
{ }
/// <summary>
/// Returns an initialized rendererInfo based on the X axis.
/// </summary>
internal override RendererInfo Init()
{
Chart chart = (Chart)_rendererParms.DrawingItem;
AxisRendererInfo xari = new AxisRendererInfo();
xari._axis = chart._xAxis;
if (xari._axis != null)
{
ChartRendererInfo cri = (ChartRendererInfo)_rendererParms.RendererInfo;
CalculateXAxisValues(xari);
InitXValues(xari);
InitAxisTitle(xari, cri.DefaultFont);
InitTickLabels(xari, cri.DefaultFont);
InitAxisLineFormat(xari);
InitGridlines(xari);
}
return xari;
}
/// <summary>
/// Calculates the space used for the X axis.
/// </summary>
internal override void Format()
{
AxisRendererInfo xari = ((ChartRendererInfo)_rendererParms.RendererInfo).xAxisRendererInfo;
if (xari._axis != null)
{
AxisTitleRendererInfo atri = xari._axisTitleRendererInfo;
// Calculate space used for axis title.
XSize titleSize = new XSize(0, 0);
if (atri != null && atri.AxisTitleText != null && atri.AxisTitleText.Length > 0)
titleSize = _rendererParms.Graphics.MeasureString(atri.AxisTitleText, atri.AxisTitleFont);
// Calculate space used for tick labels.
XSize size = new XSize(0, 0);
foreach (XSeries xs in xari.XValues)
{
foreach (XValue xv in xs)
{
XSize valueSize = _rendererParms.Graphics.MeasureString(xv._value, xari.TickLabelsFont);
size.Height += valueSize.Height;
size.Width = Math.Max(valueSize.Width, size.Width);
}
}
// Remember space for later drawing.
if (atri != null)
atri.AxisTitleSize = titleSize;
xari.TickLabelsHeight = size.Height;
xari.Height = size.Height;
xari.Width = titleSize.Width + size.Width + xari.MajorTickMarkWidth;
}
}
/// <summary>
/// Draws the horizontal X axis.
/// </summary>
internal override void Draw()
{
XGraphics gfx = _rendererParms.Graphics;
ChartRendererInfo cri = (ChartRendererInfo)_rendererParms.RendererInfo;
AxisRendererInfo xari = cri.xAxisRendererInfo;
double xMin = xari.MinimumScale;
double xMax = xari.MaximumScale;
double xMajorTick = xari.MajorTick;
double xMinorTick = xari.MinorTick;
double xMaxExtension = xari.MajorTick;
// Draw tick labels. Each tick label will be aligned centered.
int countTickLabels = (int)xMax;
double tickLabelStep = xari.Height / countTickLabels;
XPoint startPos = new XPoint(xari.X + xari.Width - xari.MajorTickMarkWidth, xari.Y + tickLabelStep / 2);
foreach (XSeries xs in xari.XValues)
{
for (int idx = countTickLabels - 1; idx >= 0; --idx)
{
XValue xv = xs[idx];
string tickLabel = xv._value;
XSize size = gfx.MeasureString(tickLabel, xari.TickLabelsFont);
gfx.DrawString(tickLabel, xari.TickLabelsFont, xari.TickLabelsBrush, startPos.X - size.Width, startPos.Y + size.Height / 2);
startPos.Y += tickLabelStep;
}
}
// Draw axis.
// First draw tick marks, second draw axis.
double majorTickMarkStart = 0, majorTickMarkEnd = 0,
minorTickMarkStart = 0, minorTickMarkEnd = 0;
GetTickMarkPos(xari, ref majorTickMarkStart, ref majorTickMarkEnd, ref minorTickMarkStart, ref minorTickMarkEnd);
LineFormatRenderer lineFormatRenderer = new LineFormatRenderer(gfx, xari.LineFormat);
XPoint[] points = new XPoint[2];
// Minor ticks.
if (xari.MinorTickMark != TickMarkType.None)
{
int countMinorTickMarks = (int)(xMax / xMinorTick);
double minorTickMarkStep = xari.Height / countMinorTickMarks;
startPos.Y = xari.Y;
for (int x = 0; x <= countMinorTickMarks; x++)
{
points[0].X = minorTickMarkStart;
points[0].Y = startPos.Y + minorTickMarkStep * x;
points[1].X = minorTickMarkEnd;
points[1].Y = points[0].Y;
lineFormatRenderer.DrawLine(points[0], points[1]);
}
}
// Major ticks.
if (xari.MajorTickMark != TickMarkType.None)
{
int countMajorTickMarks = (int)(xMax / xMajorTick);
double majorTickMarkStep = xari.Height / countMajorTickMarks;
startPos.Y = xari.Y;
for (int x = 0; x <= countMajorTickMarks; x++)
{
points[0].X = majorTickMarkStart;
points[0].Y = startPos.Y + majorTickMarkStep * x;
points[1].X = majorTickMarkEnd;
points[1].Y = points[0].Y;
lineFormatRenderer.DrawLine(points[0], points[1]);
}
}
// Axis.
if (xari.LineFormat != null)
{
points[0].X = xari.X + xari.Width;
points[0].Y = xari.Y;
points[1].X = xari.X + xari.Width;
points[1].Y = xari.Y + xari.Height;
if (xari.MajorTickMark != TickMarkType.None)
{
points[0].Y -= xari.LineFormat.Width / 2;
points[1].Y += xari.LineFormat.Width / 2;
}
lineFormatRenderer.DrawLine(points[0], points[1]);
}
// Draw axis title.
AxisTitleRendererInfo atri = xari._axisTitleRendererInfo;
if (atri != null && atri.AxisTitleText != null && atri.AxisTitleText.Length > 0)
{
XRect rect = new XRect(xari.X, xari.Y + xari.Height / 2, atri.AxisTitleSize.Width, 0);
gfx.DrawString(atri.AxisTitleText, atri.AxisTitleFont, atri.AxisTitleBrush, rect);
}
}
/// <summary>
/// Calculates the X axis describing values like minimum/maximum scale, major/minor tick and
/// major/minor tick mark width.
/// </summary>
private void CalculateXAxisValues(AxisRendererInfo rendererInfo)
{
// Calculates the maximum number of data points over all series.
SeriesCollection seriesCollection = ((Chart)rendererInfo._axis._parent)._seriesCollection;
int count = 0;
foreach (Series series in seriesCollection)
count = Math.Max(count, series.Count);
rendererInfo.MinimumScale = 0;
rendererInfo.MaximumScale = count; // At least 0
rendererInfo.MajorTick = 1;
rendererInfo.MinorTick = 0.5;
rendererInfo.MajorTickMarkWidth = DefaultMajorTickMarkWidth;
rendererInfo.MinorTickMarkWidth = DefaultMinorTickMarkWidth;
}
/// <summary>
/// Initializes the rendererInfo's xvalues. If not set by the user xvalues will be simply numbers
/// from minimum scale + 1 to maximum scale.
/// </summary>
private void InitXValues(AxisRendererInfo rendererInfo)
{
rendererInfo.XValues = ((Chart)rendererInfo._axis._parent)._xValues;
if (rendererInfo.XValues == null)
{
rendererInfo.XValues = new XValues();
XSeries xs = rendererInfo.XValues.AddXSeries();
for (double i = rendererInfo.MinimumScale + 1; i <= rendererInfo.MaximumScale; ++i)
xs.Add(i.ToString());
}
}
/// <summary>
/// Calculates the starting and ending y position for the minor and major tick marks.
/// </summary>
private void GetTickMarkPos(AxisRendererInfo rendererInfo,
ref double majorTickMarkStart, ref double majorTickMarkEnd,
ref double minorTickMarkStart, ref double minorTickMarkEnd)
{
double majorTickMarkWidth = rendererInfo.MajorTickMarkWidth;
double minorTickMarkWidth = rendererInfo.MinorTickMarkWidth;
double x = rendererInfo.Rect.X + rendererInfo.Rect.Width;
switch (rendererInfo.MajorTickMark)
{
case TickMarkType.Inside:
majorTickMarkStart = x;
majorTickMarkEnd = x + majorTickMarkWidth;
break;
case TickMarkType.Outside:
majorTickMarkStart = x - majorTickMarkWidth;
majorTickMarkEnd = x;
break;
case TickMarkType.Cross:
majorTickMarkStart = x - majorTickMarkWidth;
majorTickMarkEnd = x + majorTickMarkWidth;
break;
case TickMarkType.None:
majorTickMarkStart = 0;
majorTickMarkEnd = 0;
break;
}
switch (rendererInfo.MinorTickMark)
{
case TickMarkType.Inside:
minorTickMarkStart = x;
minorTickMarkEnd = x + minorTickMarkWidth;
break;
case TickMarkType.Outside:
minorTickMarkStart = x - minorTickMarkWidth;
minorTickMarkEnd = x;
break;
case TickMarkType.Cross:
minorTickMarkStart = x - minorTickMarkWidth;
minorTickMarkEnd = x + minorTickMarkWidth;
break;
case TickMarkType.None:
minorTickMarkStart = 0;
minorTickMarkEnd = 0;
break;
}
}
}
}

View File

@@ -0,0 +1,331 @@
#region PDFsharp Charting - A .NET charting library based on PDFsharp
//
// Authors:
// Niklas Schneider
//
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.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 System;
using PdfSharp.Drawing;
namespace PdfSharp.Charting.Renderers
{
/// <summary>
/// Represents a Y axis renderer used for charts of type Column2D or Line.
/// </summary>
internal class VerticalYAxisRenderer : YAxisRenderer
{
/// <summary>
/// Initializes a new instance of the VerticalYAxisRenderer class with the
/// specified renderer parameters.
/// </summary>
internal VerticalYAxisRenderer(RendererParameters parms)
: base(parms)
{ }
/// <summary>
/// Returns a initialized rendererInfo based on the Y axis.
/// </summary>
internal override RendererInfo Init()
{
Chart chart = (Chart)_rendererParms.DrawingItem;
XGraphics gfx = _rendererParms.Graphics;
AxisRendererInfo yari = new AxisRendererInfo();
yari._axis = chart._yAxis;
InitScale(yari);
if (yari._axis != null)
{
ChartRendererInfo cri = (ChartRendererInfo)_rendererParms.RendererInfo;
InitTickLabels(yari, cri.DefaultFont);
InitAxisTitle(yari, cri.DefaultFont);
InitAxisLineFormat(yari);
InitGridlines(yari);
}
return yari;
}
/// <summary>
/// Calculates the space used for the Y axis.
/// </summary>
internal override void Format()
{
AxisRendererInfo yari = ((ChartRendererInfo)_rendererParms.RendererInfo).yAxisRendererInfo;
if (yari._axis != null)
{
XGraphics gfx = _rendererParms.Graphics;
XSize size = new XSize(0, 0);
// height of all ticklabels
double yMin = yari.MinimumScale;
double yMax = yari.MaximumScale;
double yMajorTick = yari.MajorTick;
double lineHeight = Double.MinValue;
XSize labelSize = new XSize(0, 0);
for (double y = yMin; y <= yMax; y += yMajorTick)
{
string str = y.ToString(yari.TickLabelsFormat);
labelSize = gfx.MeasureString(str, yari.TickLabelsFont);
size.Height += labelSize.Height;
size.Width = Math.Max(size.Width, labelSize.Width);
lineHeight = Math.Max(lineHeight, labelSize.Height);
}
// add space for tickmarks
size.Width += yari.MajorTickMarkWidth * 1.5;
// Measure axis title
XSize titleSize = new XSize(0, 0);
if (yari._axisTitleRendererInfo != null)
{
RendererParameters parms = new RendererParameters();
parms.Graphics = gfx;
parms.RendererInfo = yari;
AxisTitleRenderer atr = new AxisTitleRenderer(parms);
atr.Format();
titleSize.Height = yari._axisTitleRendererInfo.Height;
titleSize.Width = yari._axisTitleRendererInfo.Width;
}
yari.Height = Math.Max(size.Height, titleSize.Height);
yari.Width = size.Width + titleSize.Width;
yari.InnerRect = yari.Rect;
yari.InnerRect.Y += yari.TickLabelsFont.Height / 2;
yari.LabelSize = labelSize;
}
}
/// <summary>
/// Draws the vertical Y axis.
/// </summary>
internal override void Draw()
{
AxisRendererInfo yari = ((ChartRendererInfo)_rendererParms.RendererInfo).yAxisRendererInfo;
double yMin = yari.MinimumScale;
double yMax = yari.MaximumScale;
double yMajorTick = yari.MajorTick;
double yMinorTick = yari.MinorTick;
XMatrix matrix = new XMatrix();
matrix.TranslatePrepend(-yari.InnerRect.X, yMax);
matrix.Scale(1, yari.InnerRect.Height / (yMax - yMin), XMatrixOrder.Append);
matrix.ScalePrepend(1, -1); // mirror horizontal
matrix.Translate(yari.InnerRect.X, yari.InnerRect.Y, XMatrixOrder.Append);
// Draw axis.
// First draw tick marks, second draw axis.
double majorTickMarkStart = 0, majorTickMarkEnd = 0,
minorTickMarkStart = 0, minorTickMarkEnd = 0;
GetTickMarkPos(yari, ref majorTickMarkStart, ref majorTickMarkEnd, ref minorTickMarkStart, ref minorTickMarkEnd);
XGraphics gfx = _rendererParms.Graphics;
LineFormatRenderer lineFormatRenderer = new LineFormatRenderer(gfx, yari.LineFormat);
LineFormatRenderer minorTickMarkLineFormat = new LineFormatRenderer(gfx, yari.MinorTickMarkLineFormat);
LineFormatRenderer majorTickMarkLineFormat = new LineFormatRenderer(gfx, yari.MajorTickMarkLineFormat);
XPoint[] points = new XPoint[2];
// Draw minor tick marks.
if (yari.MinorTickMark != TickMarkType.None)
{
for (double y = yMin + yMinorTick; y < yMax; y += yMinorTick)
{
points[0].X = minorTickMarkStart;
points[0].Y = y;
points[1].X = minorTickMarkEnd;
points[1].Y = y;
matrix.TransformPoints(points);
minorTickMarkLineFormat.DrawLine(points[0], points[1]);
}
}
double lineSpace = yari.TickLabelsFont.GetHeight(); // old: yari.TickLabelsFont.GetHeight(gfx);
int cellSpace = yari.TickLabelsFont.FontFamily.GetLineSpacing(yari.TickLabelsFont.Style);
double xHeight = yari.TickLabelsFont.Metrics.XHeight;
XSize labelSize = new XSize(0, 0);
labelSize.Height = lineSpace * xHeight / cellSpace;
int countTickLabels = (int)((yMax - yMin) / yMajorTick) + 1;
for (int i = 0; i < countTickLabels; ++i)
{
double y = yMin + yMajorTick * i;
string str = y.ToString(yari.TickLabelsFormat);
labelSize.Width = gfx.MeasureString(str, yari.TickLabelsFont).Width;
// Draw major tick marks.
if (yari.MajorTickMark != TickMarkType.None)
{
labelSize.Width += yari.MajorTickMarkWidth * 1.5;
points[0].X = majorTickMarkStart;
points[0].Y = y;
points[1].X = majorTickMarkEnd;
points[1].Y = y;
matrix.TransformPoints(points);
majorTickMarkLineFormat.DrawLine(points[0], points[1]);
}
else
labelSize.Width += SpaceBetweenLabelAndTickmark;
// Draw label text.
XPoint[] layoutText = new XPoint[1];
layoutText[0].X = yari.InnerRect.X + yari.InnerRect.Width - labelSize.Width;
layoutText[0].Y = y;
matrix.TransformPoints(layoutText);
layoutText[0].Y += labelSize.Height / 2; // Center text vertically.
gfx.DrawString(str, yari.TickLabelsFont, yari.TickLabelsBrush, layoutText[0]);
}
// Draw axis.
if (yari.LineFormat != null && yari.LineFormat.Width > 0)
{
points[0].X = yari.InnerRect.X + yari.InnerRect.Width;
points[0].Y = yMin;
points[1].X = yari.InnerRect.X + yari.InnerRect.Width;
points[1].Y = yMax;
matrix.TransformPoints(points);
if (yari.MajorTickMark != TickMarkType.None)
{
// yMax is at the upper side of the axis
points[1].Y -= yari.LineFormat.Width / 2;
points[0].Y += yari.LineFormat.Width / 2;
}
lineFormatRenderer.DrawLine(points[0], points[1]);
}
// Draw axis title
if (yari._axisTitleRendererInfo != null && yari._axisTitleRendererInfo.AxisTitleText != "")
{
RendererParameters parms = new RendererParameters();
parms.Graphics = gfx;
parms.RendererInfo = yari;
double width = yari._axisTitleRendererInfo.Width;
yari._axisTitleRendererInfo.Rect = yari.InnerRect;
yari._axisTitleRendererInfo.Width = width;
AxisTitleRenderer atr = new AxisTitleRenderer(parms);
atr.Draw();
}
}
/// <summary>
/// Calculates all values necessary for scaling the axis like minimum/maximum scale or
/// minor/major tick.
/// </summary>
private void InitScale(AxisRendererInfo rendererInfo)
{
double yMin, yMax;
CalcYAxis(out yMin, out yMax);
FineTuneYAxis(rendererInfo, yMin, yMax);
rendererInfo.MajorTickMarkWidth = DefaultMajorTickMarkWidth;
rendererInfo.MinorTickMarkWidth = DefaultMinorTickMarkWidth;
}
/// <summary>
/// Gets the top and bottom position of the major and minor tick marks depending on the
/// tick mark type.
/// </summary>
private void GetTickMarkPos(AxisRendererInfo rendererInfo,
ref double majorTickMarkStart, ref double majorTickMarkEnd,
ref double minorTickMarkStart, ref double minorTickMarkEnd)
{
double majorTickMarkWidth = rendererInfo.MajorTickMarkWidth;
double minorTickMarkWidth = rendererInfo.MinorTickMarkWidth;
XRect rect = rendererInfo.Rect;
switch (rendererInfo.MajorTickMark)
{
case TickMarkType.Inside:
majorTickMarkStart = rect.X + rect.Width;
majorTickMarkEnd = rect.X + rect.Width + majorTickMarkWidth;
break;
case TickMarkType.Outside:
majorTickMarkStart = rect.X + rect.Width;
majorTickMarkEnd = rect.X + rect.Width - majorTickMarkWidth;
break;
case TickMarkType.Cross:
majorTickMarkStart = rect.X + rect.Width - majorTickMarkWidth;
majorTickMarkEnd = rect.X + rect.Width + majorTickMarkWidth;
break;
//TickMarkType.None:
default:
majorTickMarkStart = 0;
majorTickMarkEnd = 0;
break;
}
switch (rendererInfo.MinorTickMark)
{
case TickMarkType.Inside:
minorTickMarkStart = rect.X + rect.Width;
minorTickMarkEnd = rect.X + rect.Width + minorTickMarkWidth;
break;
case TickMarkType.Outside:
minorTickMarkStart = rect.X + rect.Width;
minorTickMarkEnd = rect.X + rect.Width - minorTickMarkWidth;
break;
case TickMarkType.Cross:
minorTickMarkStart = rect.X + rect.Width - minorTickMarkWidth;
minorTickMarkEnd = rect.X + rect.Width + minorTickMarkWidth;
break;
//TickMarkType.None:
default:
minorTickMarkStart = 0;
minorTickMarkEnd = 0;
break;
}
}
/// <summary>
/// Determines the smallest and the largest number from all series of the chart.
/// </summary>
protected virtual void CalcYAxis(out double yMin, out double yMax)
{
yMin = double.MaxValue;
yMax = double.MinValue;
foreach (Series series in ((Chart)_rendererParms.DrawingItem).SeriesCollection)
{
foreach (Point point in series.Elements)
{
if (!double.IsNaN(point._value))
{
yMin = Math.Min(yMin, point.Value);
yMax = Math.Max(yMax, point.Value);
}
}
}
}
}
}

View File

@@ -0,0 +1,62 @@
#region PDFsharp Charting - A .NET charting library based on PDFsharp
//
// Authors:
// Niklas Schneider
//
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.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 PdfSharp.Drawing;
namespace PdfSharp.Charting.Renderers
{
/// <summary>
/// Represents a renderer for the plot area background.
/// </summary>
internal class WallRenderer : Renderer
{
/// <summary>
/// Initializes a new instance of the WallRenderer class with the specified renderer parameters.
/// </summary>
internal WallRenderer(RendererParameters parms)
: base(parms)
{ }
/// <summary>
/// Draws the wall.
/// </summary>
internal override void Draw()
{
ChartRendererInfo cri = (ChartRendererInfo)_rendererParms.RendererInfo;
if (cri.plotAreaRendererInfo.FillFormat != null)
{
XRect plotAreaBox = cri.plotAreaRendererInfo.Rect;
if (plotAreaBox.IsEmpty)
return;
_rendererParms.Graphics.DrawRectangle(cri.plotAreaRendererInfo.FillFormat, plotAreaBox);
}
}
}
}

View File

@@ -0,0 +1,52 @@
#region PDFsharp Charting - A .NET charting library based on PDFsharp
//
// Authors:
// Niklas Schneider
//
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.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
namespace PdfSharp.Charting.Renderers
{
/// <summary>
/// Represents the base class for all X axis renderer.
/// </summary>
internal abstract class XAxisRenderer : AxisRenderer
{
/// <summary>
/// Initializes a new instance of the XAxisRenderer class with the specified renderer parameters.
/// </summary>
internal XAxisRenderer(RendererParameters parms)
: base(parms)
{ }
/// <summary>
/// Returns the default tick labels format string.
/// </summary>
protected override string GetDefaultTickLabelsFormat()
{
return "0";
}
}
}

View File

@@ -0,0 +1,130 @@
#region PDFsharp Charting - A .NET charting library based on PDFsharp
//
// Authors:
// Niklas Schneider
//
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.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 System;
namespace PdfSharp.Charting.Renderers
{
/// <summary>
/// Represents the base class for all Y axis renderer.
/// </summary>
internal abstract class YAxisRenderer : AxisRenderer
{
/// <summary>
/// Initializes a new instance of the YAxisRenderer class with the specified renderer parameters.
/// </summary>
internal YAxisRenderer(RendererParameters parms)
: base(parms)
{ }
/// <summary>
/// Calculates optimal minimum/maximum scale and minor/major tick based on yMin and yMax.
/// </summary>
protected void FineTuneYAxis(AxisRendererInfo rendererInfo, double yMin, double yMax)
{
if (yMin == double.MaxValue && yMax == double.MinValue)
{
// No series data given.
yMin = 0.0f;
yMax = 0.9f;
}
if (yMin == yMax)
{
if (yMin == 0)
yMax = 0.9f;
else if (yMin < 0)
yMax = 0;
else if (yMin > 0)
yMax = yMin + 1;
}
// If the ratio between yMax to yMin is more than 1.2, the smallest number will be set too zero.
// It's Excel's behavior.
if (yMin != 0)
{
if (yMin < 0 && yMax < 0)
{
if (yMin / yMax >= 1.2)
yMax = 0;
}
else if (yMax / yMin >= 1.2)
yMin = 0;
}
double deltaYRaw = yMax - yMin;
int digits = (int)(Math.Log(deltaYRaw, 10) + 1);
double normed = deltaYRaw / Math.Pow(10, digits) * 10;
double normedStepWidth = 1;
if (normed < 2)
normedStepWidth = 0.2f;
else if (normed < 5)
normedStepWidth = 0.5f;
AxisRendererInfo yari = rendererInfo;
double stepWidth = normedStepWidth * Math.Pow(10.0, digits - 1.0);
if (yari._axis == null || double.IsNaN(yari._axis._majorTick))
yari.MajorTick = stepWidth;
else
yari.MajorTick = yari._axis._majorTick;
double roundFactor = stepWidth * 0.5;
if (yari._axis == null || double.IsNaN(yari._axis.MinimumScale))
{
double signumMin = (yMin != 0) ? yMin / Math.Abs(yMin) : 0;
yari.MinimumScale = (int)(Math.Abs((yMin - roundFactor) / stepWidth) - (1 * signumMin)) * stepWidth * signumMin;
}
else
yari.MinimumScale = yari._axis.MinimumScale;
if (yari._axis == null || double.IsNaN(yari._axis.MaximumScale))
{
double signumMax = (yMax != 0) ? yMax / Math.Abs(yMax) : 0;
yari.MaximumScale = (int)(Math.Abs((yMax + roundFactor) / stepWidth) + (1 * signumMax)) * stepWidth * signumMax;
}
else
yari.MaximumScale = yari._axis.MaximumScale;
if (yari._axis == null || double.IsNaN(yari._axis._minorTick))
yari.MinorTick = yari.MajorTick / 5;
else
yari.MinorTick = yari._axis._minorTick;
}
/// <summary>
/// Returns the default tick labels format string.
/// </summary>
protected override string GetDefaultTickLabelsFormat()
{
return "0.0";
}
}
}