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,192 @@
#region MigraDoc - Creating Documents on the Fly
//
// Authors:
// Klaus Potzesny
//
// Copyright (c) 2001-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.com
// http://www.migradoc.com
// http://sourceforge.net/projects/pdfsharp
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#endregion
using System;
using PdfSharp.Drawing;
namespace MigraDoc.Rendering
{
/// <summary>
/// Abstract base class for all areas to render in.
/// </summary>
public abstract class Area
{
/// <summary>
/// Gets the left boundary of the area.
/// </summary>
public abstract XUnit X { get; set; }
/// <summary>
/// Gets the top boundary of the area.
/// </summary>
public abstract XUnit Y { get; set; }
/// <summary>
/// Gets the largest fitting rect with the given y position and height.
/// </summary>
/// <param name="yPosition">Top bound of the searched rectangle.</param>
/// <param name="height">Height of the searched rectangle.</param>
/// <returns>
/// The largest fitting rect with the given y position and height.
/// Null if yPosition exceeds the area.
/// </returns>
public abstract Rectangle GetFittingRect(XUnit yPosition, XUnit height);
/// <summary>
/// Gets or sets the height of the smallest rectangle containing the area.
/// </summary>
public abstract XUnit Height { get; set; }
/// <summary>
/// Gets or sets the width of the smallest rectangle containing the area.
/// </summary>
public abstract XUnit Width { get; set; }
/// <summary>
/// Returns the union of this area snd the given one.
/// </summary>
/// <param name="area">The area to unite with.</param>
/// <returns>The union of the two areas.</returns>
public abstract Area Unite(Area area);
/// <summary>
/// Lowers the area and makes it smaller.
/// </summary>
/// <param name="verticalOffset">The measure of lowering.</param>
/// <returns>The lowered Area.</returns>
public abstract Area Lower(XUnit verticalOffset);
}
public class Rectangle : Area
{
/// <summary>
/// Initializes a new rectangle object.
/// </summary>
/// <param name="x">Left bound of the rectangle.</param>
/// <param name="y">Upper bound of the rectangle.</param>
/// <param name="width">Width of the rectangle.</param>
/// <param name="height">Height of the rectangle.</param>
public Rectangle(XUnit x, XUnit y, XUnit width, XUnit height)
{
_x = x;
_y = y;
_width = width;
_height = height;
}
/// <summary>
/// Initializes a new Rectangle by copying its values.
/// </summary>
/// <param name="rect">The rectangle to copy.</param>
public Rectangle(Rectangle rect)
{
_x = rect._x;
_y = rect._y;
_width = rect._width;
_height = rect._height;
}
/// <summary>
/// Gets the largest fitting rect with the given y position and height.
/// </summary>
/// <param name="yPosition">Top boundary of the requested rectangle.</param>
/// <param name="height">Height of the requested rectangle.</param>
/// <returns>The largest fitting rect with the given y position and height or NULL if the requested height does not fit.</returns>
public override Rectangle GetFittingRect(XUnit yPosition, XUnit height)
{
if (yPosition + height > _y + _height + Renderer.Tolerance)
return null;
return new Rectangle(_x, yPosition, _width, height);
}
/// <summary>
/// Gets or sets the left boundary of the rectangle.
/// </summary>
public override XUnit X
{
get { return _x; }
set { _x = value; }
}
XUnit _x;
/// <summary>
/// Gets or sets the top boundary of the rectangle.
/// </summary>
public override XUnit Y
{
get { return _y; }
set { _y = value; }
}
XUnit _y;
/// <summary>
/// Gets or sets the width of the rectangle.
/// </summary>
public override XUnit Width
{
get { return _width; }
set { _width = value; }
}
XUnit _width;
/// <summary>
/// Gets or sets the height of the rectangle.
/// </summary>
public override XUnit Height
{
get { return _height; }
set { _height = value; }
}
XUnit _height;
/// <summary>
/// Returns the union of the rectangle and the given area.
/// </summary>
/// <param name="area">The area to unite with.</param>
/// <returns>The union of the two areas.</returns>
public override Area Unite(Area area)
{
if (area == null)
return this;
// This implementation is of course not correct, but it works for our purposes.
XUnit minTop = Math.Min(_y, area.Y);
XUnit minLeft = Math.Min(_x, area.X);
XUnit maxRight = Math.Max(_x + _width, area.X + area.Width);
XUnit maxBottom = Math.Max(_y + _height, area.Y + area.Height);
return new Rectangle(minLeft, minTop, maxRight - minLeft, maxBottom - minTop);
}
public override Area Lower(XUnit verticalOffset)
{
return new Rectangle(_x, _y + verticalOffset, _width, _height - verticalOffset);
}
}
}

View File

@@ -0,0 +1,305 @@
#region MigraDoc - Creating Documents on the Fly
//
// Authors:
// Klaus Potzesny
//
// Copyright (c) 2001-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.com
// http://www.migradoc.com
// http://sourceforge.net/projects/pdfsharp
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#endregion
using System.Diagnostics;
using MigraDoc.DocumentObjectModel;
using MigraDoc.DocumentObjectModel.Tables;
using PdfSharp.Drawing;
namespace MigraDoc.Rendering
{
/// <summary>
/// Renders a single Border.
/// </summary>
public class BordersRenderer
{
public BordersRenderer(Borders borders, XGraphics gfx)
{
Debug.Assert(borders.Document != null);
_gfx = gfx;
_borders = borders;
}
private Border GetBorder(BorderType type)
{
return _borders.GetBorderReadOnly(type);
}
private XColor GetColor(BorderType type)
{
Color clr = Colors.Black;
Border border = GetBorder(type);
if (border != null && !border.Color.IsEmpty)
clr = border.Color;
else if (!_borders.Color.IsEmpty)
clr = _borders.Color;
#if noCMYK
return XColor.FromArgb((int)clr.Argb);
#else
// bool cmyk = false; // BUG CMYK
// if (_borders.Document != null)
// cmyk = _borders.Document.UseCmykColor;
//#if DEBUG
// else
// GetT ype();
//#endif
return ColorHelper.ToXColor(clr, _borders.Document.UseCmykColor);
#endif
}
private BorderStyle GetStyle(BorderType type)
{
BorderStyle style = BorderStyle.Single;
Border border = GetBorder(type);
if (border != null && !border._style.IsNull)
style = border.Style;
else if (!_borders._style.IsNull)
style = _borders.Style;
return style;
}
public XUnit GetWidth(BorderType type)
{
if (_borders == null)
return 0;
Border border = GetBorder(type);
if (border != null)
{
if (!border._visible.IsNull && !border.Visible)
return 0;
if (!border._width.IsNull)
return border.Width.Point;
if (!border._color.IsNull || !border._style.IsNull || border.Visible)
{
if (!_borders._width.IsNull)
return _borders.Width.Point;
return 0.5;
}
}
else if (!(type == BorderType.DiagonalDown || type == BorderType.DiagonalUp))
{
if (!_borders._visible.IsNull && !_borders.Visible)
return 0;
if (!_borders._width.IsNull)
return _borders.Width.Point;
if (!_borders._color.IsNull || !_borders._style.IsNull || _borders.Visible)
return 0.5;
}
return 0;
}
/// <summary>
/// Renders the border top down.
/// </summary>
/// <param name="type">The type of the border.</param>
/// <param name="left">The left position of the border.</param>
/// <param name="top">The top position of the border.</param>
/// <param name="height">The height on which to render the border.</param>
public void RenderVertically(BorderType type, XUnit left, XUnit top, XUnit height)
{
XUnit borderWidth = GetWidth(type);
if (borderWidth == 0)
return;
left += borderWidth / 2;
_gfx.DrawLine(GetPen(type), left, top + height, left, top);
}
/// <summary>
/// Renders the border top down.
/// </summary>
/// <param name="type">The type of the border.</param>
/// <param name="left">The left position of the border.</param>
/// <param name="top">The top position of the border.</param>
/// <param name="width">The width on which to render the border.</param>
public void RenderHorizontally(BorderType type, XUnit left, XUnit top, XUnit width)
{
XUnit borderWidth = GetWidth(type);
if (borderWidth == 0)
return;
top += borderWidth / 2;
_gfx.DrawLine(GetPen(type), left + width, top, left, top);
}
public void RenderDiagonally(BorderType type, XUnit left, XUnit top, XUnit width, XUnit height)
{
XUnit borderWidth = GetWidth(type);
if (borderWidth == 0)
return;
XGraphicsState state = _gfx.Save();
_gfx.IntersectClip(new XRect(left, top, width, height));
if (type == BorderType.DiagonalDown)
_gfx.DrawLine(GetPen(type), left, top, left + width, top + height);
else if (type == BorderType.DiagonalUp)
_gfx.DrawLine(GetPen(type), left, top + height, left + width, top);
_gfx.Restore(state);
}
public void RenderRounded(RoundedCorner roundedCorner, XUnit x, XUnit y, XUnit width, XUnit height)
{
if (roundedCorner == RoundedCorner.None)
return;
// As source we use the vertical borders.
// If not set originally, they have been set to the horizontal border values in TableRenderer.EqualizeRoundedCornerBorders().
BorderType borderType = BorderType.Top;
if (roundedCorner == RoundedCorner.TopLeft || roundedCorner == RoundedCorner.BottomLeft)
borderType = BorderType.Left;
if (roundedCorner == RoundedCorner.TopRight || roundedCorner == RoundedCorner.BottomRight)
borderType = BorderType.Right;
XUnit borderWidth = GetWidth(borderType);
XPen borderPen = GetPen(borderType);
if (borderWidth == 0)
return;
x -= borderWidth / 2;
y -= borderWidth / 2;
XUnit ellipseWidth = width * 2 + borderWidth;
XUnit ellipseHeight = height * 2 + borderWidth;
switch (roundedCorner)
{
case RoundedCorner.TopLeft:
_gfx.DrawArc(borderPen, new XRect(x, y, ellipseWidth, ellipseHeight), 180, 90);
break;
case RoundedCorner.TopRight:
_gfx.DrawArc(borderPen, new XRect(x - width, y, ellipseWidth, ellipseHeight), 270, 90);
break;
case RoundedCorner.BottomRight:
_gfx.DrawArc(borderPen, new XRect(x - width, y - height, ellipseWidth, ellipseHeight), 0, 90);
break;
case RoundedCorner.BottomLeft:
_gfx.DrawArc(borderPen, new XRect(x, y - height, ellipseWidth, ellipseHeight), 90, 90);
break;
}
}
private XPen GetPen(BorderType type)
{
XUnit borderWidth = GetWidth(type);
if (borderWidth == 0)
return null;
XPen pen = new XPen(GetColor(type), borderWidth);
BorderStyle style = GetStyle(type);
switch (style)
{
case BorderStyle.DashDot:
pen.DashStyle = XDashStyle.DashDot;
break;
case BorderStyle.DashDotDot:
pen.DashStyle = XDashStyle.DashDotDot;
break;
case BorderStyle.DashLargeGap:
pen.DashPattern = new double[] { 3, 3 };
break;
case BorderStyle.DashSmallGap:
pen.DashPattern = new double[] { 5, 1 };
break;
case BorderStyle.Dot:
pen.DashStyle = XDashStyle.Dot;
break;
case BorderStyle.Single:
default:
pen.DashStyle = XDashStyle.Solid;
break;
}
return pen;
}
public bool IsRendered(BorderType borderType)
{
if (_borders == null)
return false;
switch (borderType)
{
case BorderType.Left:
if (_borders._left == null || _borders._left.IsNull())
return false;
return GetWidth(borderType) > 0;
case BorderType.Right:
if (_borders._right == null || _borders._right.IsNull())
return false;
return GetWidth(borderType) > 0;
case BorderType.Top:
if (_borders._top == null || _borders._top.IsNull())
return false;
return GetWidth(borderType) > 0;
case BorderType.Bottom:
if (_borders._bottom == null || _borders._bottom.IsNull())
return false;
return GetWidth(borderType) > 0;
case BorderType.DiagonalDown:
if (_borders._diagonalDown == null || _borders._diagonalDown.IsNull())
return false;
return GetWidth(borderType) > 0;
case BorderType.DiagonalUp:
if (_borders._diagonalUp == null || _borders._diagonalUp.IsNull())
return false;
return GetWidth(borderType) > 0;
}
return false;
}
readonly XGraphics _gfx;
readonly Borders _borders;
}
}

View File

@@ -0,0 +1,48 @@
#region MigraDoc - Creating Documents on the Fly
//
// Authors:
// Klaus Potzesny
//
// Copyright (c) 2001-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.com
// http://www.migradoc.com
// http://sourceforge.net/projects/pdfsharp
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#endregion
using PdfSharp.Charting;
namespace MigraDoc.Rendering
{
/// <summary>
/// Formatting information for a chart.
/// </summary>
public sealed class ChartFormatInfo : ShapeFormatInfo
{
public ChartFrame ChartFrame;
public FormattedTextArea FormattedHeader;
public FormattedTextArea FormattedLeft;
public FormattedTextArea FormattedTop;
public FormattedTextArea FormattedBottom;
public FormattedTextArea FormattedRight;
public FormattedTextArea FormattedFooter;
}
}

View File

@@ -0,0 +1,48 @@
#region MigraDoc - Creating Documents on the Fly
//
// Authors:
// Klaus Potzesny
//
// Copyright (c) 2001-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.com
// http://www.migradoc.com
// http://sourceforge.net/projects/pdfsharp
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#endregion
namespace MigraDoc.Rendering
{
/// <summary>
/// Rendering information for charts.
/// </summary>
public sealed class ChartRenderInfo : ShapeRenderInfo
{
public ChartRenderInfo()
{ }
public override FormatInfo FormatInfo
{
get { return _formatInfo ?? (_formatInfo = new ChartFormatInfo()); }
set { _formatInfo = (ChartFormatInfo)value; }
}
ChartFormatInfo _formatInfo;
}
}

View File

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

View File

@@ -0,0 +1,51 @@
#region MigraDoc - Creating Documents on the Fly
//
// Authors:
// Klaus Potzesny
//
// Copyright (c) 2001-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.com
// http://www.migradoc.com
// http://sourceforge.net/projects/pdfsharp
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#endregion
using PdfSharp.Drawing;
using MigraDoc.DocumentObjectModel;
namespace MigraDoc.Rendering
{
static class ColorHelper
{
/// <summary>
/// Converts Color to XColor.
/// </summary>
public static XColor ToXColor(Color color, bool cmyk)
{
if (color.IsEmpty)
return XColor.Empty;
if (cmyk)
return XColor.FromCmyk(color.Alpha / 100.0, color.C / 100.0, color.M / 100.0, color.Y / 100.0, color.K / 100.0);
return XColor.FromArgb((int)color.Argb);
}
}
}

View File

@@ -0,0 +1,405 @@
#region MigraDoc - Creating Documents on the Fly
//
// Authors:
// Klaus Potzesny
//
// Copyright (c) 2001-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.com
// http://www.migradoc.com
// http://sourceforge.net/projects/pdfsharp
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#endregion
using System;
using System.Collections.Generic;
using MigraDoc.DocumentObjectModel;
using PdfSharp.Pdf;
using PdfSharp.Drawing;
using MigraDoc.DocumentObjectModel.Visitors;
using MigraDoc.DocumentObjectModel.Shapes;
using MigraDoc.DocumentObjectModel.Tables;
using MigraDoc.Rendering.Resources;
namespace MigraDoc.Rendering
{
/// <summary>
/// Provides methods to render the document or single parts of it to a XGraphics object.
/// </summary>
/// <remarks>
/// One prepared instance of this class can serve to render several output formats.
/// </remarks>
public class DocumentRenderer
{
/// <summary>
/// Initializes a new instance of the DocumentRenderer class.
/// </summary>
/// <param name="document">The migradoc document to render.</param>
public DocumentRenderer(Document document)
{
_document = document;
}
/// <summary>
/// Prepares this instance for rendering.
/// </summary>
public void PrepareDocument()
{
PdfFlattenVisitor visitor = new PdfFlattenVisitor();
visitor.Visit(_document);
_previousListNumbers = new Dictionary<ListType, int>(3);
_previousListNumbers[ListType.NumberList1] = 0;
_previousListNumbers[ListType.NumberList2] = 0;
_previousListNumbers[ListType.NumberList3] = 0;
_formattedDocument = new FormattedDocument(_document, this);
//REM: Size should not be necessary in this case.
#if true
XGraphics gfx = XGraphics.CreateMeasureContext(new XSize(2000, 2000), XGraphicsUnit.Point, XPageDirection.Downwards);
#else
#if GDI
XGraphics gfx = XGraphics.FromGraphics(Graphics.FromHwnd(IntPtr.Zero), new XSize(2000, 2000));
#endif
#if WPF
XGraphics gfx = XGraphics.FromDrawingContext(null, new XSize(2000, 2000), XGraphicsUnit.Point);
#endif
#endif
// _previousListNumber = int.MinValue;
//gfx.MUH = _unicode;
//gfx.MFEH = _fontEmbedding;
_previousListInfo = null;
_formattedDocument.Format(gfx);
}
/// <summary>
/// Occurs while the document is being prepared (can be used to show a progress bar).
/// </summary>
public event PrepareDocumentProgressEventHandler PrepareDocumentProgress;
/// <summary>
/// Allows applications to display a progress indicator while PrepareDocument() is being executed.
/// </summary>
/// <param name="value"></param>
/// <param name="maximum"></param>
public virtual void OnPrepareDocumentProgress(int value, int maximum)
{
if (PrepareDocumentProgress != null)
{
// Invokes the delegates.
PrepareDocumentProgressEventArgs e = new PrepareDocumentProgressEventArgs(value, maximum);
PrepareDocumentProgress(this, e);
}
}
/// <summary>
/// Gets a value indicating whether this instance supports PrepareDocumentProgress.
/// </summary>
public bool HasPrepareDocumentProgress
{
get { return PrepareDocumentProgress != null; }
}
/// <summary>
/// Gets the formatted document of this instance.
/// </summary>
public FormattedDocument FormattedDocument
{
get { return _formattedDocument; }
}
FormattedDocument _formattedDocument;
/// <summary>
/// Renders a MigraDoc document to the specified graphics object.
/// </summary>
public void RenderPage(XGraphics gfx, int page)
{
RenderPage(gfx, page, PageRenderOptions.All);
}
/// <summary>
/// Renders a MigraDoc document to the specified graphics object.
/// </summary>
public void RenderPage(XGraphics gfx, int page, PageRenderOptions options)
{
if (_formattedDocument.IsEmptyPage(page))
return;
FieldInfos fieldInfos = _formattedDocument.GetFieldInfos(page);
fieldInfos.Date = _printDate != DateTime.MinValue ? _printDate : DateTime.Now;
if ((options & PageRenderOptions.RenderHeader) == PageRenderOptions.RenderHeader)
RenderHeader(gfx, page);
if ((options & PageRenderOptions.RenderFooter) == PageRenderOptions.RenderFooter)
RenderFooter(gfx, page);
if ((options & PageRenderOptions.RenderContent) == PageRenderOptions.RenderContent)
{
RenderInfo[] renderInfos = _formattedDocument.GetRenderInfos(page);
//foreach (RenderInfo renderInfo in renderInfos)
int count = renderInfos.Length;
for (int idx = 0; idx < count; idx++)
{
RenderInfo renderInfo = renderInfos[idx];
Renderer renderer = Renderer.Create(gfx, this, renderInfo, fieldInfos);
renderer.Render();
}
}
}
/// <summary>
/// Gets the document objects that get rendered on the specified page.
/// </summary>
public DocumentObject[] GetDocumentObjectsFromPage(int page)
{
RenderInfo[] renderInfos = _formattedDocument.GetRenderInfos(page);
int count = renderInfos != null ? renderInfos.Length : 0;
DocumentObject[] documentObjects = new DocumentObject[count];
for (int idx = 0; idx < count; idx++)
documentObjects[idx] = renderInfos[idx].DocumentObject;
return documentObjects;
}
/// <summary>
/// Gets the render information for document objects that get rendered on the specified page.
/// </summary>
public RenderInfo[] GetRenderInfoFromPage(int page)
{
return _formattedDocument.GetRenderInfos(page);
}
/// <summary>
/// Renders a single object to the specified graphics object at the given point.
/// </summary>
/// <param name="graphics">The graphics object to render on.</param>
/// <param name="xPosition">The left position of the rendered object.</param>
/// <param name="yPosition">The top position of the rendered object.</param>
/// <param name="width">The width.</param>
/// <param name="documentObject">The document object to render. Can be paragraph, table, or shape.</param>
/// <remarks>This function is still in an experimental state.</remarks>
public void RenderObject(XGraphics graphics, XUnit xPosition, XUnit yPosition, XUnit width, DocumentObject documentObject)
{
if (graphics == null)
throw new ArgumentNullException("graphics");
if (documentObject == null)
throw new ArgumentNullException("documentObject");
if (!(documentObject is Shape) && !(documentObject is Table) &&
!(documentObject is Paragraph))
throw new ArgumentException(Messages2.ObjectNotRenderable, "documentObject");
Renderer renderer = Renderer.Create(graphics, this, documentObject, null);
renderer.Format(new Rectangle(xPosition, yPosition, width, double.MaxValue), null);
RenderInfo renderInfo = renderer.RenderInfo;
renderInfo.LayoutInfo.ContentArea.X = xPosition;
renderInfo.LayoutInfo.ContentArea.Y = yPosition;
renderer = Renderer.Create(graphics, this, renderer.RenderInfo, null);
renderer.Render();
}
/// <summary>
/// Gets or sets the working directory for rendering.
/// </summary>
public string WorkingDirectory
{
get { return _workingDirectory; }
set { _workingDirectory = value; }
}
string _workingDirectory;
private void RenderHeader(XGraphics graphics, int page)
{
FormattedHeaderFooter formattedHeader = _formattedDocument.GetFormattedHeader(page);
if (formattedHeader == null)
return;
Rectangle headerArea = _formattedDocument.GetHeaderArea(page);
RenderInfo[] renderInfos = formattedHeader.GetRenderInfos();
FieldInfos fieldInfos = _formattedDocument.GetFieldInfos(page);
foreach (RenderInfo renderInfo in renderInfos)
{
Renderer renderer = Renderer.Create(graphics, this, renderInfo, fieldInfos);
renderer.Render();
}
}
private void RenderFooter(XGraphics graphics, int page)
{
FormattedHeaderFooter formattedFooter = _formattedDocument.GetFormattedFooter(page);
if (formattedFooter == null)
return;
Rectangle footerArea = _formattedDocument.GetFooterArea(page);
RenderInfo[] renderInfos = formattedFooter.GetRenderInfos();
#if true
#if true
// The footer is bottom-aligned and grows with its contents. topY specifies the Y position where the footer begins.
XUnit topY = footerArea.Y + footerArea.Height - RenderInfo.GetTotalHeight(renderInfos);
// Hack: The purpose of "topY" is unclear, but two paragraphs in the footer will use the same topY and will be rendered at the same position.
// offsetY specifies the offset (amount of movement) for all footer items. It's the difference between topY and the position calculated for the first item.
XUnit offsetY = 0;
bool notFirst = false;
FieldInfos fieldInfos = _formattedDocument.GetFieldInfos(page);
foreach (RenderInfo renderInfo in renderInfos)
{
Renderer renderer = Renderer.Create(graphics, this, renderInfo, fieldInfos);
if (!notFirst)
{
offsetY = renderer.RenderInfo.LayoutInfo.ContentArea.Y - topY;
notFirst = true;
}
XUnit savedY = renderer.RenderInfo.LayoutInfo.ContentArea.Y;
// Apply offsetY only to items that do not have an absolute position.
if (renderer.RenderInfo.LayoutInfo.Floating != Floating.None)
renderer.RenderInfo.LayoutInfo.ContentArea.Y -= offsetY;
renderer.Render();
renderer.RenderInfo.LayoutInfo.ContentArea.Y = savedY;
}
#else
// TODO Document the purpose of "topY".
XUnit topY = footerArea.Y + footerArea.Height - RenderInfo.GetTotalHeight(renderInfos);
// Hack: The purpose of "topY" is unclear, but two paragraphs in the footer will use the same topY and will be rendered at the same position.
XUnit offsetY = 0;
FieldInfos fieldInfos = _formattedDocument.GetFieldInfos(page);
foreach (RenderInfo renderInfo in renderInfos)
{
Renderer renderer = Renderer.Create(graphics, this, renderInfo, fieldInfos);
XUnit savedY = renderer.RenderInfo.LayoutInfo.ContentArea.Y;
renderer.RenderInfo.LayoutInfo.ContentArea.Y = topY + offsetY;
renderer.Render();
renderer.RenderInfo.LayoutInfo.ContentArea.Y = savedY;
offsetY += renderer.RenderInfo.LayoutInfo.ContentArea.Height;
}
#endif
#else
XUnit topY = footerArea.Y + footerArea.Height - RenderInfo.GetTotalHeight(renderInfos);
FieldInfos fieldInfos = _formattedDocument.GetFieldInfos(page);
foreach (RenderInfo renderInfo in renderInfos)
{
Renderer renderer = Renderer.Create(graphics, this, renderInfo, fieldInfos);
XUnit savedY = renderer.RenderInfo.LayoutInfo.ContentArea.Y;
renderer.RenderInfo.LayoutInfo.ContentArea.Y = topY;
renderer.Render();
renderer.RenderInfo.LayoutInfo.ContentArea.Y = savedY;
}
#endif
}
public void AddOutline(int level, string title, PdfPage destinationPage)
{
if (level < 1 || destinationPage == null)
return;
PdfDocument document = destinationPage.Owner;
if (document == null)
return;
PdfOutlineCollection outlines = document.Outlines;
while (--level > 0)
{
int count = outlines.Count;
if (count == 0)
{
// You cannot add empty bookmarks to PDF. So we use blank here.
PdfOutline outline = outlines.Add(" ", destinationPage, true);
outlines = outline.Outlines;
}
else
outlines = outlines[count - 1].Outlines;
}
outlines.Add(title, destinationPage, true);
}
public int NextListNumber(ListInfo listInfo)
{
ListType listType = listInfo.ListType;
bool isNumberList = listType == ListType.NumberList1 ||
listType == ListType.NumberList2 ||
listType == ListType.NumberList3;
int listNumber = int.MinValue;
if (listInfo == _previousListInfo)
{
if (isNumberList)
return _previousListNumbers[listType];
return listNumber;
}
//bool listTypeChanged = _previousListInfo == null || _previousListInfo.ListType != listType;
if (isNumberList)
{
listNumber = 1;
if (/*!listTypeChanged &&*/ (listInfo._continuePreviousList.IsNull || listInfo.ContinuePreviousList))
listNumber = _previousListNumbers[listType] + 1;
_previousListNumbers[listType] = listNumber;
}
_previousListInfo = listInfo;
return listNumber;
}
ListInfo _previousListInfo;
Dictionary<ListType, int> _previousListNumbers;
private readonly Document _document;
public DateTime _printDate = DateTime.MinValue;
/// <summary>
/// Arguments for the PrepareDocumentProgressEvent which is called while a document is being prepared (you can use this to display a progress bar).
/// </summary>
public class PrepareDocumentProgressEventArgs : EventArgs
{
/// <summary>
/// Indicates the current step reached in document preparation.
/// </summary>
public int Value;
/// <summary>
/// Indicates the final step in document preparation. The quitient of Value and Maximum can be used to calculate a percentage (e. g. for use in a progress bar).
/// </summary>
public int Maximum;
/// <summary>
/// Initializes a new instance of the <see cref="PrepareDocumentProgressEventArgs"/> class.
/// </summary>
/// <param name="value">The current step in document preparation.</param>
/// <param name="maximum">The latest step in document preparation.</param>
public PrepareDocumentProgressEventArgs(int value, int maximum)
{
Value = value;
Maximum = maximum;
}
}
/// <summary>
/// The event handler that is being called for the PrepareDocumentProgressEvent event.
/// </summary>
public delegate void PrepareDocumentProgressEventHandler(object sender, PrepareDocumentProgressEventArgs e);
public int ProgressMaximum;
public int ProgressCompleted;
}
}

View File

@@ -0,0 +1,98 @@
#region MigraDoc - Creating Documents on the Fly
//
// Authors:
// Klaus Potzesny
//
// Copyright (c) 2001-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.com
// http://www.migradoc.com
// http://sourceforge.net/projects/pdfsharp
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#endregion
using System;
using System.Collections.Generic;
namespace MigraDoc.Rendering
{
/// <summary>
/// Field information used to fill fields when rendering or formatting.
/// </summary>
public class FieldInfos
{
public FieldInfos(Dictionary<string, BookmarkInfo> bookmarks)
{
_bookmarks = bookmarks;
}
public void AddBookmark(string name)
{
if (PhysicalPageNr <= 0)
return;
if (_bookmarks.ContainsKey(name))
_bookmarks.Remove(name);
if (PhysicalPageNr > 0)
_bookmarks.Add(name, new BookmarkInfo(PhysicalPageNr, DisplayPageNr));
}
public int GetShownPageNumber(string bookmarkName)
{
if (_bookmarks.ContainsKey(bookmarkName))
{
BookmarkInfo bi = _bookmarks[bookmarkName];
return bi.ShownPageNumber;
}
return -1;
}
public int GetPhysicalPageNumber(string bookmarkName)
{
if (_bookmarks.ContainsKey(bookmarkName))
{
BookmarkInfo bi = _bookmarks[bookmarkName];
return bi.DisplayPageNumber;
}
return -1;
}
public struct BookmarkInfo
{
public BookmarkInfo(int physicalPageNumber, int displayPageNumber)
{
DisplayPageNumber = physicalPageNumber;
ShownPageNumber = displayPageNumber;
}
public readonly int DisplayPageNumber;
public readonly int ShownPageNumber;
}
readonly Dictionary<string, BookmarkInfo> _bookmarks;
public int DisplayPageNr;
public int PhysicalPageNr;
public int Section;
public int SectionPages;
public int NumPages;
public DateTime Date;
}
}

View File

@@ -0,0 +1,79 @@
#region MigraDoc - Creating Documents on the Fly
//
// Authors:
// Klaus Potzesny
//
// Copyright (c) 2001-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.com
// http://www.migradoc.com
// http://sourceforge.net/projects/pdfsharp
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#endregion
using PdfSharp.Drawing;
using MigraDoc.DocumentObjectModel.Shapes;
namespace MigraDoc.Rendering
{
/// <summary>
/// Renders fill formats.
/// </summary>
public class FillFormatRenderer
{
public FillFormatRenderer(FillFormat fillFormat, XGraphics gfx)
{
_gfx = gfx;
_fillFormat = fillFormat;
}
public void Render(XUnit x, XUnit y, XUnit width, XUnit height)
{
XBrush brush = GetBrush();
if (brush == null)
return;
_gfx.DrawRectangle(brush, x.Point, y.Point, width.Point, height.Point);
}
private bool IsVisible()
{
if (!_fillFormat._visible.IsNull)
return _fillFormat.Visible;
return !_fillFormat._color.IsNull;
}
private XBrush GetBrush()
{
if (_fillFormat == null || !IsVisible())
return null;
#if noCMYK
return new XSolidBrush(XColor.FromArgb(_fillFormat.Color.Argb));
#else
return new XSolidBrush(ColorHelper.ToXColor(_fillFormat.Color, _fillFormat.Document.UseCmykColor));
#endif
}
readonly XGraphics _gfx;
readonly FillFormat _fillFormat;
}
}

View File

@@ -0,0 +1,141 @@
#region MigraDoc - Creating Documents on the Fly
//
// Authors:
// Klaus Potzesny
//
// Copyright (c) 2001-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.com
// http://www.migradoc.com
// http://sourceforge.net/projects/pdfsharp
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#endregion
#define CACHE_FONTS_
using System;
using PdfSharp.Pdf;
using PdfSharp.Drawing;
using MigraDoc.DocumentObjectModel;
namespace MigraDoc.Rendering
{
/// <summary>
/// Helps measuring and handling fonts.
/// </summary>
public class FontHandler
{
#if DEBUG
public static int CreateFontCounter;
#endif
/// <summary>
/// Converts a DOM Font to an XFont.
/// </summary>
public static XFont FontToXFont(Font font, PdfFontEncoding encoding)
{
XPdfFontOptions options = new XPdfFontOptions(encoding);
XFontStyle style = GetXStyle(font);
#if DEBUG
if (StringComparer.OrdinalIgnoreCase.Compare(font.Name, "Segoe UI Semilight") == 0
&& (style & XFontStyle.BoldItalic) == XFontStyle.Italic)
font.GetType();
#endif
XFont xFont = new XFont(font.Name, font.Size, style, options);
#if DEBUG
CreateFontCounter++;
#endif
return xFont;
}
public static XFontStyle GetXStyle(Font font)
{
XFontStyle style = XFontStyle.Regular;
if (font.Bold)
style = font.Italic ? XFontStyle.BoldItalic : XFontStyle.Bold;
else if (font.Italic)
style = XFontStyle.Italic;
return style;
}
public static XUnit GetDescent(XFont font)
{
XUnit descent = font.Metrics.Descent;
descent *= font.Size;
descent /= font.FontFamily.GetEmHeight(font.Style);
return descent;
}
public static XUnit GetAscent(XFont font)
{
XUnit ascent = font.Metrics.Ascent;
ascent *= font.Size;
ascent /= font.FontFamily.GetEmHeight(font.Style);
return ascent;
}
public static double GetSubSuperScaling(XFont font)
{
return 0.8 * GetAscent(font) / font.GetHeight();
}
public static XFont ToSubSuperFont(XFont font)
{
double size = font.Size * GetSubSuperScaling(font);
return new XFont(font.Name, size, font.Style, font.PdfOptions);
}
public static XBrush FontColorToXBrush(Font font)
{
#if noCMYK
return new XSolidBrush(XColor.FromArgb((int)font.Color.A, (int)font.Color.R, (int)font.Color.G, (int)font.Color.B));
#else
return new XSolidBrush(ColorHelper.ToXColor(font.Color, font.Document.UseCmykColor));
#endif
}
#if CACHE_FONTS
static XFont XFontFromCache(Font font, bool unicode, PdfFontEmbedding fontEmbedding)
{
XFont xFont = null;
XPdfFontOptions options = null;
options = new XPdfFontOptions(fontEmbedding, unicode);
XFontStyle style = GetXStyle(font);
xFont = new XFont(font.Name, font.Size, style, options);
return xFont;
}
static string BuildSignature(Font font, bool unicode, PdfFontEmbedding fontEmbedding)
{
StringBuilder signature = new StringBuilder(128);
signature.Append(font.Name.ToLower());
signature.Append(font.Size.Point.ToString("##0.0"));
return signature.ToString();
}
static Hash_table fontCache = new Hash_table();
#endif
}
}

View File

@@ -0,0 +1,83 @@
#region MigraDoc - Creating Documents on the Fly
//
// Authors:
// Klaus Potzesny
//
// Copyright (c) 2001-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.com
// http://www.migradoc.com
// http://sourceforge.net/projects/pdfsharp
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#endregion
namespace MigraDoc.Rendering
{
/// <summary>
/// Abstract base class for formatting information received by calling Format() on a renderer.
/// </summary>
public abstract class FormatInfo
{
/// <summary>
/// Indicates that the formatted object is starting.
/// </summary>
public abstract bool IsStarting
{
get;
}
/// <summary>
/// Indicates that the formatted object is ending.
/// </summary>
public abstract bool IsEnding
{
get;
}
/// <summary>
/// Indicates that the formatted object is complete.
/// </summary>
public abstract bool IsComplete
{
get;
}
/// <summary>
/// Indicates that the starting of the element is completed
/// </summary>
public abstract bool StartingIsComplete
{
get;
}
/// <summary>
/// Indicates that the ending of the element is completed
/// </summary>
public abstract bool EndingIsComplete
{
get;
}
public abstract bool IsEmpty
{
get;
}
}
}

View File

@@ -0,0 +1,201 @@
#region MigraDoc - Creating Documents on the Fly
//
// Authors:
// Klaus Potzesny
//
// Copyright (c) 2001-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.com
// http://www.migradoc.com
// http://sourceforge.net/projects/pdfsharp
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#endregion
using System;
using System.Collections.Generic;
using MigraDoc.DocumentObjectModel;
using PdfSharp.Drawing;
using MigraDoc.DocumentObjectModel.Tables;
namespace MigraDoc.Rendering
{
/// <summary>
/// Represents a formatted cell.
/// </summary>
public class FormattedCell : IAreaProvider
{
public FormattedCell(Cell cell, DocumentRenderer documentRenderer, Borders cellBorders, FieldInfos fieldInfos, XUnit xOffset, XUnit yOffset)
{
_cell = cell;
_fieldInfos = fieldInfos;
_yOffset = yOffset;
_xOffset = xOffset;
_bordersRenderer = new BordersRenderer(cellBorders, null);
_documentRenderer = documentRenderer;
}
Area IAreaProvider.GetNextArea()
{
if (_isFirstArea)
{
Rectangle rect = CalcContentRect();
_isFirstArea = false;
return rect;
}
return null;
}
bool _isFirstArea = true;
Area IAreaProvider.ProbeNextArea()
{
return null;
}
public void Format(XGraphics gfx)
{
_gfx = gfx;
_formatter = new TopDownFormatter(this, _documentRenderer, _cell.Elements);
_formatter.FormatOnAreas(gfx, false);
_contentHeight = CalcContentHeight(_documentRenderer);
}
private Rectangle CalcContentRect()
{
Column column = _cell.Column;
XUnit width = InnerWidth;
width -= column.LeftPadding.Point;
Column rightColumn = _cell.Table.Columns[column.Index + _cell.MergeRight];
width -= rightColumn.RightPadding.Point;
XUnit height = double.MaxValue;
return new Rectangle(_xOffset, _yOffset, width, height);
}
public XUnit ContentHeight
{
get { return _contentHeight; }
}
public XUnit InnerHeight
{
get
{
Row row = _cell.Row;
XUnit verticalPadding = row.TopPadding.Point;
verticalPadding += row.BottomPadding.Point;
switch (row.HeightRule)
{
case RowHeightRule.Exactly:
return row.Height.Point;
case RowHeightRule.Auto:
return verticalPadding + _contentHeight;
case RowHeightRule.AtLeast:
default:
return Math.Max(row.Height, verticalPadding + _contentHeight);
}
}
}
public XUnit InnerWidth
{
get
{
XUnit width = 0;
int cellColumnIdx = _cell.Column.Index;
for (int toRight = 0; toRight <= _cell.MergeRight; ++toRight)
{
int columnIdx = cellColumnIdx + toRight;
width += _cell.Table.Columns[columnIdx].Width;
}
width -= _bordersRenderer.GetWidth(BorderType.Right);
return width;
}
}
FieldInfos IAreaProvider.AreaFieldInfos
{
get { return _fieldInfos; }
}
void IAreaProvider.StoreRenderInfos(List<RenderInfo> renderInfos)
{
_renderInfos = renderInfos;
}
bool IAreaProvider.IsAreaBreakBefore(LayoutInfo layoutInfo)
{
return false;
}
bool IAreaProvider.PositionVertically(LayoutInfo layoutInfo)
{
return false;
}
bool IAreaProvider.PositionHorizontally(LayoutInfo layoutInfo)
{
return false;
}
private XUnit CalcContentHeight(DocumentRenderer documentRenderer)
{
XUnit height = RenderInfo.GetTotalHeight(GetRenderInfos());
if (height == 0)
{
height = ParagraphRenderer.GetLineHeight(_cell.Format, _gfx, documentRenderer);
height += _cell.Format.SpaceBefore;
height += _cell.Format.SpaceAfter;
}
return height;
}
XUnit _contentHeight = 0;
public RenderInfo[] GetRenderInfos()
{
if (_renderInfos != null)
return _renderInfos.ToArray();
return null;
}
readonly FieldInfos _fieldInfos;
List<RenderInfo> _renderInfos;
readonly XUnit _xOffset;
readonly XUnit _yOffset;
/// <summary>
/// Gets the cell the formatting information refers to.
/// </summary>
public Cell Cell
{
get { return _cell;}
}
readonly Cell _cell;
TopDownFormatter _formatter;
readonly BordersRenderer _bordersRenderer;
XGraphics _gfx;
readonly DocumentRenderer _documentRenderer;
}
}

View File

@@ -0,0 +1,725 @@
#region MigraDoc - Creating Documents on the Fly
//
// Authors:
// Klaus Potzesny
//
// Copyright (c) 2001-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.com
// http://www.migradoc.com
// http://sourceforge.net/projects/pdfsharp
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#endregion
using System;
using System.Collections.Generic;
using System.Globalization;
using PdfSharp;
using PdfSharp.Drawing;
using MigraDoc.DocumentObjectModel;
using MigraDoc.DocumentObjectModel.publics;
namespace MigraDoc.Rendering
{
/// <summary>
/// Represents a formatted document.
/// </summary>
public class FormattedDocument : IAreaProvider
{
enum PagePosition
{
First,
Odd,
Even
}
private struct HeaderFooterPosition
{
public HeaderFooterPosition(int sectionNr, PagePosition pagePosition)
{
_sectionNr = sectionNr;
_pagePosition = pagePosition;
}
public override bool Equals(object obj)
{
if (obj is HeaderFooterPosition)
{
HeaderFooterPosition hfp = (HeaderFooterPosition)obj;
return _sectionNr == hfp._sectionNr && _pagePosition == hfp._pagePosition;
}
return false;
}
public override int GetHashCode()
{
return _sectionNr.GetHashCode() ^ _pagePosition.GetHashCode();
}
readonly int _sectionNr;
readonly PagePosition _pagePosition;
}
public FormattedDocument(Document document, DocumentRenderer documentRenderer)
{
_document = document;
_documentRenderer = documentRenderer;
}
/// <summary>
/// Formats the document by performing line breaks and page breaks.
/// </summary>
public void Format(XGraphics gfx)
{
_bookmarks = new Dictionary<string, FieldInfos.BookmarkInfo>();
_pageRenderInfos = new Dictionary<int, List<RenderInfo>>();
_pageInfos = new Dictionary<int, PageInfo>();
_pageFieldInfos = new Dictionary<int, FieldInfos>();
_formattedHeaders = new Dictionary<HeaderFooterPosition, FormattedHeaderFooter>();
_formattedFooters = new Dictionary<HeaderFooterPosition, FormattedHeaderFooter>();
_gfx = gfx;
_currentPage = 0;
_sectionNumber = 0;
_pageCount = 0;
_shownPageNumber = 0;
_documentRenderer.ProgressCompleted = 0;
_documentRenderer.ProgressMaximum = 0;
if (_documentRenderer.HasPrepareDocumentProgress)
{
foreach (Section section in _document.Sections)
_documentRenderer.ProgressMaximum += section.Elements.Count;
}
foreach (Section section in _document.Sections)
{
_isNewSection = true;
_currentSection = section;
++_sectionNumber;
if (NeedsEmptyPage())
InsertEmptyPage();
TopDownFormatter formatter = new TopDownFormatter(this, _documentRenderer, section.Elements);
formatter.FormatOnAreas(gfx, true);
FillSectionPagesInfo();
_documentRenderer.ProgressCompleted += section.Elements.Count;
}
_pageCount = _currentPage;
FillNumPagesInfo();
}
PagePosition CurrentPagePosition
{
get
{
if (_isNewSection)
return PagePosition.First;
// Choose header and footer based on the shown page number, not the physical page number.
if (_shownPageNumber % 2 == 0)
return PagePosition.Even;
return PagePosition.Odd;
}
}
void FormatHeadersFooters()
{
HeadersFooters headers = (HeadersFooters)_currentSection.GetValue("Headers", GV.ReadOnly);
if (headers != null)
{
PagePosition pagePos = CurrentPagePosition;
HeaderFooterPosition hfp = new HeaderFooterPosition(_sectionNumber, pagePos);
if (!_formattedHeaders.ContainsKey(hfp))
FormatHeader(hfp, ChooseHeaderFooter(headers, pagePos));
}
HeadersFooters footers = (HeadersFooters)_currentSection.GetValue("Footers", GV.ReadOnly);
if (footers != null)
{
PagePosition pagePos = CurrentPagePosition;
HeaderFooterPosition hfp = new HeaderFooterPosition(_sectionNumber, pagePos);
if (!_formattedFooters.ContainsKey(hfp))
FormatFooter(hfp, ChooseHeaderFooter(footers, pagePos));
}
}
void FormatHeader(HeaderFooterPosition hfp, HeaderFooter header)
{
if (header != null && !_formattedHeaders.ContainsKey(hfp))
{
FormattedHeaderFooter formattedHeaderFooter = new FormattedHeaderFooter(header, _documentRenderer, _currentFieldInfos);
formattedHeaderFooter.ContentRect = GetHeaderArea(_currentSection, _currentPage);
formattedHeaderFooter.Format(_gfx);
_formattedHeaders.Add(hfp, formattedHeaderFooter);
}
}
void FormatFooter(HeaderFooterPosition hfp, HeaderFooter footer)
{
if (footer != null && !_formattedFooters.ContainsKey(hfp))
{
FormattedHeaderFooter formattedHeaderFooter = new FormattedHeaderFooter(footer, _documentRenderer, _currentFieldInfos);
formattedHeaderFooter.ContentRect = GetFooterArea(_currentSection, _currentPage);
formattedHeaderFooter.Format(_gfx);
_formattedFooters.Add(hfp, formattedHeaderFooter);
}
}
/// <summary>
/// Fills the number pages information after formatting the document.
/// </summary>
void FillNumPagesInfo()
{
for (int page = 1; page <= _pageCount; ++page)
{
if (IsEmptyPage(page))
continue;
FieldInfos fieldInfos = _pageFieldInfos[page];
fieldInfos.NumPages = _pageCount;
}
}
/// <summary>
/// Fills the section pages information after formatting a section.
/// </summary>
void FillSectionPagesInfo()
{
for (int page = _currentPage; page > 0; --page)
{
if (IsEmptyPage(page))
continue;
FieldInfos fieldInfos = _pageFieldInfos[page];
if (fieldInfos.Section != _sectionNumber)
break;
fieldInfos.SectionPages = _sectionPages;
}
}
Rectangle CalcContentRect(int page)
{
PageSetup pageSetup = _currentSection.PageSetup;
XUnit width = pageSetup.EffectivePageWidth.Point;
width -= pageSetup.RightMargin.Point;
width -= pageSetup.LeftMargin.Point;
XUnit height = pageSetup.EffectivePageHeight.Point;
height -= pageSetup.TopMargin.Point;
height -= pageSetup.BottomMargin.Point;
XUnit x;
XUnit y = pageSetup.TopMargin.Point;
if (pageSetup.MirrorMargins)
x = page % 2 == 0 ? pageSetup.RightMargin.Point : pageSetup.LeftMargin.Point;
else
x = pageSetup.LeftMargin.Point;
return new Rectangle(x, y, width, height);
}
/// <summary>
/// Gets the rendering informations for the page content.
/// </summary>
/// <param name="page">The page to render.</param>
/// <returns>Rendering information for the page content.</returns>
public RenderInfo[] GetRenderInfos(int page)
{
if (_pageRenderInfos.ContainsKey(page))
return (_pageRenderInfos[page]).ToArray();
return null;
}
private Dictionary<int, List<RenderInfo>> _pageRenderInfos;
/// <summary>
/// Gets a formatted headerfooter object for header of the given page.
/// </summary>
/// <param name="page">The physical page the header shall appear on.</param>
/// <returns>The required header, null if none exists to render.</returns>
public FormattedHeaderFooter GetFormattedHeader(int page)
{
FieldInfos fieldInfos = _pageFieldInfos[page];
int logicalPage = fieldInfos.DisplayPageNr;
PagePosition pagePos = logicalPage % 2 == 0 ? PagePosition.Even : PagePosition.Odd;
if (page == 1)
pagePos = PagePosition.First;
else //page > 1
{
if (IsEmptyPage(page - 1)) // these empty pages only occur between sections.
pagePos = PagePosition.First;
else
{
FieldInfos prevFieldInfos = _pageFieldInfos[page - 1];
if (fieldInfos.Section != prevFieldInfos.Section)
pagePos = PagePosition.First;
}
}
HeaderFooterPosition hfp = new HeaderFooterPosition(fieldInfos.Section, pagePos);
if (_formattedHeaders.ContainsKey(hfp))
return _formattedHeaders[hfp];
return null;
}
/// <summary>
/// Gets a formatted headerfooter object for footer of the given page.
/// </summary>
/// <param name="page">The physical page the footer shall appear on.</param>
/// <returns>The required footer, null if none exists to render.</returns>
public FormattedHeaderFooter GetFormattedFooter(int page)
{
FieldInfos fieldInfos = _pageFieldInfos[page];
int logicalPage = fieldInfos.DisplayPageNr;
PagePosition pagePos = logicalPage % 2 == 0 ? PagePosition.Even : PagePosition.Odd;
if (page == 1)
pagePos = PagePosition.First;
else //page > 1
{
if (IsEmptyPage(page - 1)) // these empty pages only occur between sections.
pagePos = PagePosition.First;
else
{
FieldInfos prevFieldInfos = _pageFieldInfos[page - 1];
if (fieldInfos.Section != prevFieldInfos.Section)
pagePos = PagePosition.First;
}
}
HeaderFooterPosition hfp = new HeaderFooterPosition(fieldInfos.Section, pagePos);
if (_formattedFooters.ContainsKey(hfp))
return _formattedFooters[hfp];
return null;
}
private Rectangle GetHeaderArea(Section section, int page)
{
PageSetup pageSetup = section.PageSetup;
XUnit xPos;
if (pageSetup.MirrorMargins && page % 2 == 0)
xPos = pageSetup.RightMargin.Point;
else
xPos = pageSetup.LeftMargin.Point;
XUnit width = pageSetup.EffectivePageWidth.Point;
width -= pageSetup.LeftMargin + pageSetup.RightMargin;
XUnit yPos = pageSetup.HeaderDistance.Point;
XUnit height = pageSetup.TopMargin - pageSetup.HeaderDistance;
return new Rectangle(xPos, yPos, width, height);
}
public Rectangle GetHeaderArea(int page)
{
FieldInfos fieldInfos = _pageFieldInfos[page];
Section section = _document.Sections[fieldInfos.Section - 1];
return GetHeaderArea(section, page);
}
public Rectangle GetFooterArea(int page)
{
FieldInfos fieldInfos = _pageFieldInfos[page];
Section section = _document.Sections[fieldInfos.Section - 1];
return GetFooterArea(section, page);
}
private Rectangle GetFooterArea(Section section, int page)
{
PageSetup pageSetup = section.PageSetup;
XUnit xPos;
if (pageSetup.MirrorMargins && page % 2 == 0)
xPos = pageSetup.RightMargin.Point;
else
xPos = pageSetup.LeftMargin.Point;
XUnit width = pageSetup.EffectivePageWidth.Point;
width -= pageSetup.LeftMargin + pageSetup.RightMargin;
XUnit yPos = pageSetup.EffectivePageHeight.Point;
yPos -= pageSetup.BottomMargin.Point;
XUnit height = pageSetup.BottomMargin - pageSetup.FooterDistance;
return new Rectangle(xPos, yPos, width, height);
}
private HeaderFooter ChooseHeaderFooter(HeadersFooters hfs, PagePosition pagePos)
{
if (hfs == null)
return null;
PageSetup pageSetup = _currentSection.PageSetup;
if (pagePos == PagePosition.First)
{
if (pageSetup.DifferentFirstPageHeaderFooter)
return (HeaderFooter)hfs.GetValue("FirstPage", GV.ReadOnly);
}
if (pagePos == PagePosition.Even || _shownPageNumber/*_currentPage*/ % 2 == 0)
{
if (pageSetup.OddAndEvenPagesHeaderFooter)
return (HeaderFooter)hfs.GetValue("EvenPage", GV.ReadOnly);
}
return (HeaderFooter)hfs.GetValue("Primary", GV.ReadOnly);
}
/// <summary>
/// Gets the number of pages of the document.
/// </summary>
public int PageCount
{
get { return _pageCount; }
}
int _pageCount;
/// <summary>
/// Gets information about the specified page.
/// </summary>
/// <param name="page">The page the information is asked for.</param>
/// <returns>The page information.</returns>
public PageInfo GetPageInfo(int page)
{
if (page < 1 || page > _pageCount)
#if !SILVERLIGHT
throw new ArgumentOutOfRangeException("page", page, page.ToString(CultureInfo.InvariantCulture));
#else
throw new PdfSharp.ArgumentOutOfRangeException("page", page, page.ToString(CultureInfo.InvariantCulture));
#endif
return _pageInfos[page];
}
#region IAreaProvider Members
Area IAreaProvider.GetNextArea()
{
if (_isNewSection)
_sectionPages = 0;
++_currentPage;
++_shownPageNumber;
++_sectionPages;
InitFieldInfos();
FormatHeadersFooters();
_isNewSection = false;
return CalcContentRect(_currentPage);
}
int _currentPage;
Area IAreaProvider.ProbeNextArea()
{
return CalcContentRect(_currentPage + 1);
}
void InitFieldInfos()
{
_currentFieldInfos = new FieldInfos(_bookmarks);
_currentFieldInfos.PhysicalPageNr = _currentPage;
_currentFieldInfos.Section = _sectionNumber;
if (_isNewSection && !_currentSection.PageSetup._startingNumber.IsNull)
_shownPageNumber = _currentSection.PageSetup.StartingNumber;
_currentFieldInfos.DisplayPageNr = _shownPageNumber;
}
void IAreaProvider.StoreRenderInfos(List<RenderInfo> renderInfos)
{
_pageRenderInfos.Add(_currentPage, renderInfos);
XSize pageSize = CalcPageSize(_currentSection.PageSetup);
PageOrientation pageOrientation = CalcPageOrientation(_currentSection.PageSetup);
PageInfo pageInfo = new PageInfo(pageSize.Width, pageSize.Height, pageOrientation);
_pageInfos.Add(_currentPage, pageInfo);
_pageFieldInfos.Add(_currentPage, _currentFieldInfos);
}
PageOrientation CalcPageOrientation(PageSetup pageSetup)
{
PageOrientation pageOrientation = PageOrientation.Portrait;
if (_currentSection.PageSetup.Orientation == Orientation.Landscape)
pageOrientation = PageOrientation.Landscape;
return pageOrientation;
}
XSize CalcPageSize(PageSetup pageSetup)
{
return new XSize(pageSetup.PageWidth.Point, pageSetup.PageHeight.Point);
}
bool IAreaProvider.PositionHorizontally(LayoutInfo layoutInfo)
{
switch (layoutInfo.HorizontalReference)
{
case HorizontalReference.PageMargin:
case HorizontalReference.AreaBoundary:
return PositionHorizontallyToMargin(layoutInfo);
case HorizontalReference.Page:
return PositionHorizontallyToPage(layoutInfo);
}
return false;
}
/// <summary>
/// Gets the alignment depending on the currentPage for the alignments "Outside" and "Inside".
/// </summary>
/// <param name="alignment">The original alignment</param>
/// <returns>the alignment depending on the currentPage for the alignments "Outside" and "Inside"</returns>
private ElementAlignment GetCurrentAlignment(ElementAlignment alignment)
{
ElementAlignment align = alignment;
if (align == ElementAlignment.Inside)
{
align = _currentPage % 2 == 0 ? ElementAlignment.Far : ElementAlignment.Near;
}
else if (align == ElementAlignment.Outside)
{
align = _currentPage % 2 == 0 ? ElementAlignment.Near : ElementAlignment.Far;
}
return align;
}
bool PositionHorizontallyToMargin(LayoutInfo layoutInfo)
{
Rectangle rect = CalcContentRect(_currentPage);
ElementAlignment align = GetCurrentAlignment(layoutInfo.HorizontalAlignment);
switch (align)
{
case ElementAlignment.Near:
if (layoutInfo.Left != 0)
{
layoutInfo.ContentArea.X += layoutInfo.Left;
return true;
}
if (layoutInfo.MarginLeft != 0)
{
layoutInfo.ContentArea.X += layoutInfo.MarginLeft;
return true;
}
return false;
case ElementAlignment.Far:
XUnit xPos = rect.X + rect.Width;
xPos -= layoutInfo.ContentArea.Width;
xPos -= layoutInfo.MarginRight;
layoutInfo.ContentArea.X = xPos;
return true;
case ElementAlignment.Center:
xPos = rect.Width;
xPos -= layoutInfo.ContentArea.Width;
xPos = rect.X + xPos / 2;
layoutInfo.ContentArea.X = xPos;
return true;
}
return false;
}
bool PositionHorizontallyToPage(LayoutInfo layoutInfo)
{
XUnit xPos;
ElementAlignment align = GetCurrentAlignment(layoutInfo.HorizontalAlignment);
switch (align)
{
case ElementAlignment.Near:
#if true
// Attempt to make it compatible with MigraDoc CPP.
// Ignore layoutInfo.Left if absolute position is specified in layoutInfo.MarginLeft.
// Use layoutInfo.Left if layoutInfo.MarginLeft is 0.
// TODO We would need HasValue for XUnit to determine whether a value was assigned.
if (layoutInfo.HorizontalReference == HorizontalReference.Page ||
layoutInfo.HorizontalReference == HorizontalReference.PageMargin)
xPos = layoutInfo.MarginLeft != 0 ? layoutInfo.MarginLeft : layoutInfo.Left;
else
xPos = Math.Max(layoutInfo.MarginLeft, layoutInfo.Left);
#else
if (layoutInfo.HorizontalReference == HorizontalReference.Page ||
layoutInfo.HorizontalReference == HorizontalReference.PageMargin)
xPos = layoutInfo.MarginLeft; // ignore layoutInfo.Left if absolute position is specified
else
xPos = Math.Max(layoutInfo.MarginLeft, layoutInfo.Left);
#endif
layoutInfo.ContentArea.X = xPos;
break;
case ElementAlignment.Far:
xPos = _currentSection.PageSetup.EffectivePageWidth.Point;
xPos -= layoutInfo.ContentArea.Width;
xPos -= layoutInfo.MarginRight;
layoutInfo.ContentArea.X = xPos;
break;
case ElementAlignment.Center:
xPos = _currentSection.PageSetup.EffectivePageWidth.Point;
xPos -= layoutInfo.ContentArea.Width;
xPos /= 2;
layoutInfo.ContentArea.X = xPos;
break;
}
return true;
}
bool PositionVerticallyToMargin(LayoutInfo layoutInfo)
{
Rectangle rect = CalcContentRect(_currentPage);
XUnit yPos;
switch (layoutInfo.VerticalAlignment)
{
case ElementAlignment.Near:
yPos = rect.Y;
if (layoutInfo.Top == 0)
yPos += layoutInfo.MarginTop;
else
yPos += layoutInfo.Top;
layoutInfo.ContentArea.Y = yPos;
break;
case ElementAlignment.Far:
yPos = rect.Y + rect.Height;
yPos -= layoutInfo.ContentArea.Height;
yPos -= layoutInfo.MarginBottom;
layoutInfo.ContentArea.Y = yPos;
break;
case ElementAlignment.Center:
yPos = rect.Height;
yPos -= layoutInfo.ContentArea.Height;
yPos = rect.Y + yPos / 2;
layoutInfo.ContentArea.Y = yPos;
break;
}
return true;
}
bool NeedsEmptyPage()
{
int nextPage = _currentPage + 1;
PageSetup pageSetup = _currentSection.PageSetup;
bool startOnEvenPage = pageSetup.SectionStart == BreakType.BreakEvenPage;
bool startOnOddPage = pageSetup.SectionStart == BreakType.BreakOddPage;
if (startOnOddPage)
return nextPage % 2 == 0;
if (startOnEvenPage)
return nextPage % 2 == 1;
return false;
}
void InsertEmptyPage()
{
++_currentPage;
++_shownPageNumber;
_emptyPages.Add(_currentPage, null);
XSize pageSize = CalcPageSize(_currentSection.PageSetup);
PageOrientation pageOrientation = CalcPageOrientation(_currentSection.PageSetup);
PageInfo pageInfo = new PageInfo(pageSize.Width, pageSize.Height, pageOrientation);
_pageInfos.Add(_currentPage, pageInfo);
}
bool PositionVerticallyToPage(LayoutInfo layoutInfo)
{
XUnit yPos;
switch (layoutInfo.VerticalAlignment)
{
case ElementAlignment.Near:
yPos = Math.Max(layoutInfo.MarginTop, layoutInfo.Top);
layoutInfo.ContentArea.Y = yPos;
break;
case ElementAlignment.Far:
yPos = _currentSection.PageSetup.EffectivePageHeight.Point;
yPos -= layoutInfo.ContentArea.Height;
yPos -= layoutInfo.MarginBottom;
layoutInfo.ContentArea.Y = yPos;
break;
case ElementAlignment.Center:
yPos = _currentSection.PageSetup.EffectivePageHeight.Point;
yPos -= layoutInfo.ContentArea.Height;
yPos /= 2;
layoutInfo.ContentArea.Y = yPos;
break;
}
return true;
}
bool IAreaProvider.PositionVertically(LayoutInfo layoutInfo)
{
switch (layoutInfo.VerticalReference)
{
case VerticalReference.PreviousElement:
return false;
case VerticalReference.AreaBoundary:
case VerticalReference.PageMargin:
return PositionVerticallyToMargin(layoutInfo);
case VerticalReference.Page:
return PositionVerticallyToPage(layoutInfo);
}
return false;
}
public FieldInfos GetFieldInfos(int page)
{
return _pageFieldInfos[page];
}
FieldInfos IAreaProvider.AreaFieldInfos
{
get { return _currentFieldInfos; }
}
bool IAreaProvider.IsAreaBreakBefore(LayoutInfo layoutInfo)
{
return layoutInfo.PageBreakBefore;
}
public bool IsEmptyPage(int page)
{
return _emptyPages.ContainsKey(page);
}
#endregion
Dictionary<string, FieldInfos.BookmarkInfo> _bookmarks;
int _sectionPages;
int _shownPageNumber;
int _sectionNumber;
Section _currentSection;
bool _isNewSection;
FieldInfos _currentFieldInfos;
Dictionary<int, FieldInfos> _pageFieldInfos;
Dictionary<HeaderFooterPosition, FormattedHeaderFooter> _formattedHeaders;
Dictionary<HeaderFooterPosition, FormattedHeaderFooter> _formattedFooters;
readonly DocumentRenderer _documentRenderer;
XGraphics _gfx;
Dictionary<int, PageInfo> _pageInfos;
readonly Dictionary<int, object> _emptyPages = new Dictionary<int, object>();
readonly Document _document;
}
}

View File

@@ -0,0 +1,128 @@
#region MigraDoc - Creating Documents on the Fly
//
// Authors:
// Klaus Potzesny
//
// Copyright (c) 2001-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.com
// http://www.migradoc.com
// http://sourceforge.net/projects/pdfsharp
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#endregion
using System.Collections.Generic;
using MigraDoc.DocumentObjectModel;
using PdfSharp.Drawing;
namespace MigraDoc.Rendering
{
/// <summary>
/// Represents a formatted header or footer.
/// </summary>
public class FormattedHeaderFooter : IAreaProvider
{
public FormattedHeaderFooter(HeaderFooter headerFooter, DocumentRenderer documentRenderer, FieldInfos fieldInfos)
{
_headerFooter = headerFooter;
_fieldInfos = fieldInfos;
_documentRenderer = documentRenderer;
}
public void Format(XGraphics gfx)
{
_gfx = gfx;
_isFirstArea = true;
_formatter = new TopDownFormatter(this, _documentRenderer, _headerFooter.Elements);
_formatter.FormatOnAreas(gfx, false);
_contentHeight = RenderInfo.GetTotalHeight(GetRenderInfos());
}
Area IAreaProvider.GetNextArea()
{
if (_isFirstArea)
return new Rectangle(ContentRect.X, ContentRect.Y, ContentRect.Width, double.MaxValue);
return null;
}
Area IAreaProvider.ProbeNextArea()
{
return null;
}
FieldInfos IAreaProvider.AreaFieldInfos
{
get { return _fieldInfos; }
}
void IAreaProvider.StoreRenderInfos(List<RenderInfo> renderInfos)
{
_renderInfos = renderInfos;
}
bool IAreaProvider.IsAreaBreakBefore(LayoutInfo layoutInfo)
{
return false;
}
public RenderInfo[] GetRenderInfos()
{
if (_renderInfos != null)
return _renderInfos.ToArray();
return new RenderInfo[0];
}
public Rectangle ContentRect
{
get { return _contentRect; }
set { _contentRect = value; }
}
private Rectangle _contentRect;
XUnit ContentHeight
{
get { return _contentHeight; }
}
private XUnit _contentHeight;
bool IAreaProvider.PositionVertically(LayoutInfo layoutInfo)
{
IAreaProvider formattedDoc = _documentRenderer.FormattedDocument;
return formattedDoc.PositionVertically(layoutInfo);
}
bool IAreaProvider.PositionHorizontally(LayoutInfo layoutInfo)
{
IAreaProvider formattedDoc = _documentRenderer.FormattedDocument;
return formattedDoc.PositionHorizontally(layoutInfo);
}
HeaderFooter _headerFooter;
FieldInfos _fieldInfos;
TopDownFormatter _formatter;
List<RenderInfo> _renderInfos;
XGraphics _gfx;
bool _isFirstArea;
readonly DocumentRenderer _documentRenderer;
}
}

View File

@@ -0,0 +1,171 @@
#region MigraDoc - Creating Documents on the Fly
//
// Authors:
// Klaus Potzesny
//
// Copyright (c) 2001-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.com
// http://www.migradoc.com
// http://sourceforge.net/projects/pdfsharp
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#endregion
using System;
using System.Collections.Generic;
using MigraDoc.DocumentObjectModel;
using MigraDoc.DocumentObjectModel.Shapes.Charts;
using PdfSharp.Drawing;
namespace MigraDoc.Rendering
{
/// <summary>
/// Represents a formatted text area.
/// </summary>
public class FormattedTextArea : IAreaProvider
{
public FormattedTextArea(DocumentRenderer documentRenderer, TextArea textArea, FieldInfos fieldInfos)
{
TextArea = textArea;
_fieldInfos = fieldInfos;
_documentRenderer = documentRenderer;
}
public void Format(XGraphics gfx)
{
_gfx = gfx;
_isFirstArea = true;
_formatter = new TopDownFormatter(this, _documentRenderer, TextArea.Elements);
_formatter.FormatOnAreas(gfx, false);
}
public XUnit InnerWidth
{
set { _innerWidth = value; }
get
{
if (double.IsNaN(_innerWidth))
{
if (!TextArea._width.IsNull)
_innerWidth = TextArea.Width.Point;
else
_innerWidth = CalcInherentWidth();
}
return _innerWidth;
}
}
XUnit _innerWidth = double.NaN;
public XUnit InnerHeight
{
get
{
if (TextArea._height.IsNull)
return ContentHeight + TextArea.TopPadding + TextArea.BottomPadding;
return TextArea.Height.Point;
}
}
XUnit CalcInherentWidth()
{
XUnit inherentWidth = 0;
foreach (DocumentObject obj in TextArea.Elements)
{
Renderer renderer = Renderer.Create(_gfx, _documentRenderer, obj, _fieldInfos);
if (renderer != null)
{
renderer.Format(new Rectangle(0, 0, double.MaxValue, double.MaxValue), null);
inherentWidth = Math.Max(renderer.RenderInfo.LayoutInfo.MinWidth, inherentWidth);
}
}
inherentWidth += TextArea.LeftPadding;
inherentWidth += TextArea.RightPadding;
return inherentWidth;
}
Area IAreaProvider.GetNextArea()
{
if (_isFirstArea)
return CalcContentRect();
return null;
}
Area IAreaProvider.ProbeNextArea()
{
return null;
}
FieldInfos IAreaProvider.AreaFieldInfos
{
get { return _fieldInfos; }
}
void IAreaProvider.StoreRenderInfos(List<RenderInfo> renderInfos)
{
_renderInfos = renderInfos;
}
bool IAreaProvider.IsAreaBreakBefore(LayoutInfo layoutInfo)
{
return false;
}
public RenderInfo[] GetRenderInfos()
{
if (_renderInfos != null)
return _renderInfos.ToArray();
return null;
}
public XUnit ContentHeight
{
get { return RenderInfo.GetTotalHeight(GetRenderInfos()); }
}
Rectangle CalcContentRect()
{
XUnit width = InnerWidth - TextArea.LeftPadding - TextArea.RightPadding;
XUnit height = double.MaxValue;
return new Rectangle(0, 0, width, height);
}
bool IAreaProvider.PositionVertically(LayoutInfo layoutInfo)
{
return false;
}
bool IAreaProvider.PositionHorizontally(LayoutInfo layoutInfo)
{
return false;
}
public readonly TextArea TextArea;
readonly FieldInfos _fieldInfos;
TopDownFormatter _formatter;
List<RenderInfo> _renderInfos;
XGraphics _gfx;
bool _isFirstArea;
readonly DocumentRenderer _documentRenderer;
}
}

View File

@@ -0,0 +1,180 @@
#region MigraDoc - Creating Documents on the Fly
//
// Authors:
// Klaus Potzesny
//
// Copyright (c) 2001-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.com
// http://www.migradoc.com
// http://sourceforge.net/projects/pdfsharp
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#endregion
using System.Collections.Generic;
using MigraDoc.DocumentObjectModel.Shapes;
using PdfSharp.Drawing;
namespace MigraDoc.Rendering
{
/// <summary>
/// Represents a formatted text frame.
/// </summary>
public class FormattedTextFrame : IAreaProvider
{
public FormattedTextFrame(TextFrame textframe, DocumentRenderer documentRenderer, FieldInfos fieldInfos)
{
_textframe = textframe;
_fieldInfos = fieldInfos;
_documentRenderer = documentRenderer;
}
public void Format(XGraphics gfx)
{
_gfx = gfx;
_isFirstArea = true;
_formatter = new TopDownFormatter(this, _documentRenderer, _textframe.Elements);
_formatter.FormatOnAreas(gfx, false);
_contentHeight = RenderInfo.GetTotalHeight(GetRenderInfos());
}
Area IAreaProvider.GetNextArea()
{
if (_isFirstArea)
return CalcContentRect();
return null;
}
Area IAreaProvider.ProbeNextArea()
{
return null;
}
FieldInfos IAreaProvider.AreaFieldInfos
{
get { return _fieldInfos; }
}
void IAreaProvider.StoreRenderInfos(List<RenderInfo> renderInfos)
{
_renderInfos = renderInfos;
}
bool IAreaProvider.IsAreaBreakBefore(LayoutInfo layoutInfo)
{
return false;
}
public RenderInfo[] GetRenderInfos()
{
if (_renderInfos != null)
return _renderInfos.ToArray();
return null;
}
Rectangle CalcContentRect()
{
LineFormatRenderer lfr = new LineFormatRenderer(_textframe.LineFormat, _gfx);
XUnit lineWidth = lfr.GetWidth();
XUnit width;
XUnit xOffset = lineWidth / 2;
XUnit yOffset = lineWidth / 2;
if (_textframe.Orientation == TextOrientation.Horizontal ||
_textframe.Orientation == TextOrientation.HorizontalRotatedFarEast)
{
width = _textframe.Width.Point;
xOffset += _textframe.MarginLeft;
yOffset += _textframe.MarginTop;
width -= xOffset;
width -= _textframe.MarginRight + lineWidth / 2;
}
else
{
width = _textframe.Height.Point;
if (_textframe.Orientation == TextOrientation.Upward)
{
xOffset += _textframe.MarginBottom;
yOffset += _textframe.MarginLeft;
width -= xOffset;
width -= _textframe.MarginTop + lineWidth / 2;
}
else
{
xOffset += _textframe.MarginTop;
yOffset += _textframe.MarginRight;
width -= xOffset;
width -= _textframe.MarginBottom + lineWidth / 2;
}
}
XUnit height = double.MaxValue;
return new Rectangle(xOffset, yOffset, width, height);
}
XUnit ContentHeight
{
get { return _contentHeight; }
}
bool IAreaProvider.PositionVertically(LayoutInfo layoutInfo)
{
return false;
}
bool IAreaProvider.PositionHorizontally(LayoutInfo layoutInfo)
{
Rectangle rect = CalcContentRect();
switch (layoutInfo.HorizontalAlignment)
{
case ElementAlignment.Near:
if (layoutInfo.Left != 0)
{
layoutInfo.ContentArea.X += layoutInfo.Left;
return true;
}
return false;
case ElementAlignment.Far:
XUnit xPos = rect.X + rect.Width;
xPos -= layoutInfo.ContentArea.Width;
xPos -= layoutInfo.MarginRight;
layoutInfo.ContentArea.X = xPos;
return true;
case ElementAlignment.Center:
xPos = rect.Width;
xPos -= layoutInfo.ContentArea.Width;
xPos = rect.X + xPos / 2;
layoutInfo.ContentArea.X = xPos;
return true;
}
return false;
}
readonly TextFrame _textframe;
readonly FieldInfos _fieldInfos;
TopDownFormatter _formatter;
List<RenderInfo> _renderInfos;
XGraphics _gfx;
bool _isFirstArea;
XUnit _contentHeight;
readonly DocumentRenderer _documentRenderer;
}
}

View File

@@ -0,0 +1,78 @@
#region MigraDoc - Creating Documents on the Fly
//
// Authors:
// Klaus Potzesny
//
// Copyright (c) 2001-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.com
// http://www.migradoc.com
// http://sourceforge.net/projects/pdfsharp
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#endregion
using System.Collections.Generic;
namespace MigraDoc.Rendering
{
/// <summary>
/// Represents a class that provides a series of Areas to render into.
/// </summary>
public interface IAreaProvider
{
/// <summary>
/// Gets the next area to render into.
/// </summary>
Area GetNextArea();
/// <summary>
/// Probes the next area to render into like GetNextArea, but doesn't change the provider state.
/// </summary>
/// <returns>The area for the next rendering act.</returns>
Area ProbeNextArea();
FieldInfos AreaFieldInfos { get; }
/// <summary>
/// Determines whether the element requires an area break before.
/// </summary>
bool IsAreaBreakBefore(LayoutInfo layoutInfo);
/// <summary>
/// Positions the element vertically relatively to the current area.
/// </summary>
/// <param name="layoutInfo">The layout info of the element.</param>
/// <returns>True, if the element was moved by the function.</returns>
bool PositionVertically(LayoutInfo layoutInfo);
/// <summary>
/// Positions the element horizontally relatively to the current area.
/// </summary>
/// <param name="layoutInfo">The layout info of the element.</param>
/// <returns>True, if the element was moved by the function.</returns>
bool PositionHorizontally(LayoutInfo layoutInfo);
/// <summary>
/// Stores the RenderInfos of elements on the current area.
/// </summary>
/// <param name="renderInfos"></param>
void StoreRenderInfos(List<RenderInfo> renderInfos);
}
}

View File

@@ -0,0 +1,50 @@
#region MigraDoc - Creating Documents on the Fly
//
// Authors:
// Klaus Potzesny
//
// Copyright (c) 2001-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.com
// http://www.migradoc.com
// http://sourceforge.net/projects/pdfsharp
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#endregion
using PdfSharp.Drawing;
namespace MigraDoc.Rendering
{
/// <summary>
/// Formatting information for an image.
/// </summary>
public sealed class ImageFormatInfo : ShapeFormatInfo
{
public int CropX;
public int CropY;
public int CropWidth;
public int CropHeight;
public XUnit Width;
public XUnit Height;
public ImageFailure Failure;
public string ImagePath;
}
}

View File

@@ -0,0 +1,48 @@
#region MigraDoc - Creating Documents on the Fly
//
// Authors:
// Klaus Potzesny
//
// Copyright (c) 2001-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.com
// http://www.migradoc.com
// http://sourceforge.net/projects/pdfsharp
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#endregion
namespace MigraDoc.Rendering
{
/// <summary>
/// Represents rendering information for images.
/// </summary>
public sealed class ImageRenderInfo : ShapeRenderInfo
{
/// <summary>
/// Gets the format information in a specific derived type. For a table, for example, this will be a TableFormatInfo with information about the first and last row showing on a page.
/// </summary>
public override FormatInfo FormatInfo
{
get { return _formatInfo ?? (_formatInfo = new ImageFormatInfo()); }
set { _formatInfo = (ImageFormatInfo)value; }
}
ImageFormatInfo _formatInfo;
}
}

View File

@@ -0,0 +1,367 @@
#region MigraDoc - Creating Documents on the Fly
//
// Authors:
// Klaus Potzesny
//
// Copyright (c) 2001-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.com
// http://www.migradoc.com
// http://sourceforge.net/projects/pdfsharp
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#endregion
using System;
using System.IO;
using System.Diagnostics;
using PdfSharp.Drawing;
using MigraDoc.DocumentObjectModel.Shapes;
using MigraDoc.Rendering.Resources;
namespace MigraDoc.Rendering
{
/// <summary>
/// Renders images.
/// </summary>
public class ImageRenderer : ShapeRenderer
{
public ImageRenderer(XGraphics gfx, Image image, FieldInfos fieldInfos)
: base(gfx, image, fieldInfos)
{
_image = image;
ImageRenderInfo renderInfo = new ImageRenderInfo();
renderInfo.DocumentObject = _shape;
_renderInfo = renderInfo;
}
public ImageRenderer(XGraphics gfx, RenderInfo renderInfo, FieldInfos fieldInfos)
: base(gfx, renderInfo, fieldInfos)
{
_image = (Image)renderInfo.DocumentObject;
}
public override void Format(Area area, FormatInfo previousFormatInfo)
{
_imageFilePath = _image.GetFilePath(_documentRenderer.WorkingDirectory);
// The Image is stored in the string if path starts with "base64:", otherwise we check whether the file exists.
if (!_imageFilePath.StartsWith("base64:") &&
!XImage.ExistsFile(_imageFilePath))
{
_failure = ImageFailure.FileNotFound;
Debug.WriteLine(Messages2.ImageNotFound(_image.Name), "warning");
}
ImageFormatInfo formatInfo = (ImageFormatInfo)_renderInfo.FormatInfo;
formatInfo.Failure = _failure;
formatInfo.ImagePath = _imageFilePath;
CalculateImageDimensions();
base.Format(area, previousFormatInfo);
}
protected override XUnit ShapeHeight
{
get
{
ImageFormatInfo formatInfo = (ImageFormatInfo)_renderInfo.FormatInfo;
return formatInfo.Height + _lineFormatRenderer.GetWidth();
}
}
protected override XUnit ShapeWidth
{
get
{
ImageFormatInfo formatInfo = (ImageFormatInfo)_renderInfo.FormatInfo;
return formatInfo.Width + _lineFormatRenderer.GetWidth();
}
}
public override void Render()
{
RenderFilling();
ImageFormatInfo formatInfo = (ImageFormatInfo)_renderInfo.FormatInfo;
Area contentArea = _renderInfo.LayoutInfo.ContentArea;
XRect destRect = new XRect(contentArea.X, contentArea.Y, formatInfo.Width, formatInfo.Height);
if (formatInfo.Failure == ImageFailure.None)
{
XImage xImage = null;
try
{
XRect srcRect = new XRect(formatInfo.CropX, formatInfo.CropY, formatInfo.CropWidth, formatInfo.CropHeight);
//xImage = XImage.FromFile(formatInfo.ImagePath);
xImage = CreateXImage(formatInfo.ImagePath);
_gfx.DrawImage(xImage, destRect, srcRect, XGraphicsUnit.Point); //Pixel.
}
catch (Exception)
{
RenderFailureImage(destRect);
}
finally
{
if (xImage != null)
xImage.Dispose();
}
}
else
RenderFailureImage(destRect);
RenderLine();
}
void RenderFailureImage(XRect destRect)
{
_gfx.DrawRectangle(XBrushes.LightGray, destRect);
string failureString;
ImageFormatInfo formatInfo = (ImageFormatInfo)RenderInfo.FormatInfo;
switch (formatInfo.Failure)
{
case ImageFailure.EmptySize:
failureString = Messages2.DisplayEmptyImageSize;
break;
case ImageFailure.FileNotFound:
failureString = Messages2.DisplayImageFileNotFound;
break;
case ImageFailure.InvalidType:
failureString = Messages2.DisplayInvalidImageType;
break;
case ImageFailure.NotRead:
default:
failureString = Messages2.DisplayImageNotRead;
break;
}
// Create stub font
XFont font = new XFont("Courier New", 8);
_gfx.DrawString(failureString, font, XBrushes.Red, destRect, XStringFormats.Center);
}
private void CalculateImageDimensions()
{
ImageFormatInfo formatInfo = (ImageFormatInfo)_renderInfo.FormatInfo;
if (formatInfo.Failure == ImageFailure.None)
{
XImage xImage = null;
try
{
//xImage = XImage.FromFile(_imageFilePath);
xImage = CreateXImage(_imageFilePath);
}
catch (InvalidOperationException ex)
{
Debug.WriteLine(Messages2.InvalidImageType(ex.Message));
formatInfo.Failure = ImageFailure.InvalidType;
}
if (formatInfo.Failure == ImageFailure.None)
{
try
{
XUnit usrWidth = _image.Width.Point;
XUnit usrHeight = _image.Height.Point;
bool usrWidthSet = !_image._width.IsNull;
bool usrHeightSet = !_image._height.IsNull;
XUnit resultWidth = usrWidth;
XUnit resultHeight = usrHeight;
Debug.Assert(xImage != null);
double xPixels = xImage.PixelWidth;
bool usrResolutionSet = !_image._resolution.IsNull;
double horzRes = usrResolutionSet ? _image.Resolution : xImage.HorizontalResolution;
double vertRes = usrResolutionSet ? _image.Resolution : xImage.VerticalResolution;
// ReSharper disable CompareOfFloatsByEqualityOperator
if (horzRes == 0 && vertRes == 0)
{
horzRes = 72;
vertRes = 72;
}
else if (horzRes == 0)
{
Debug.Assert(false, "How can this be?");
horzRes = 72;
}
else if (vertRes == 0)
{
Debug.Assert(false, "How can this be?");
vertRes = 72;
}
// ReSharper restore CompareOfFloatsByEqualityOperator
XUnit inherentWidth = XUnit.FromInch(xPixels / horzRes);
double yPixels = xImage.PixelHeight;
XUnit inherentHeight = XUnit.FromInch(yPixels / vertRes);
//bool lockRatio = _image.IsNull("LockAspectRatio") ? true : _image.LockAspectRatio;
bool lockRatio = _image._lockAspectRatio.IsNull || _image.LockAspectRatio;
double scaleHeight = _image.ScaleHeight;
double scaleWidth = _image.ScaleWidth;
//bool scaleHeightSet = !_image.IsNull("ScaleHeight");
//bool scaleWidthSet = !_image.IsNull("ScaleWidth");
bool scaleHeightSet = !_image._scaleHeight.IsNull;
bool scaleWidthSet = !_image._scaleWidth.IsNull;
if (lockRatio && !(scaleHeightSet && scaleWidthSet))
{
if (usrWidthSet && !usrHeightSet)
{
resultHeight = inherentHeight / inherentWidth * usrWidth;
}
else if (usrHeightSet && !usrWidthSet)
{
resultWidth = inherentWidth / inherentHeight * usrHeight;
}
// ReSharper disable once ConditionIsAlwaysTrueOrFalse
else if (!usrHeightSet && !usrWidthSet)
{
resultHeight = inherentHeight;
resultWidth = inherentWidth;
}
if (scaleHeightSet)
{
resultHeight = resultHeight * scaleHeight;
resultWidth = resultWidth * scaleHeight;
}
if (scaleWidthSet)
{
resultHeight = resultHeight * scaleWidth;
resultWidth = resultWidth * scaleWidth;
}
}
else
{
if (!usrHeightSet)
resultHeight = inherentHeight;
if (!usrWidthSet)
resultWidth = inherentWidth;
if (scaleHeightSet)
resultHeight = resultHeight * scaleHeight;
if (scaleWidthSet)
resultWidth = resultWidth * scaleWidth;
}
formatInfo.CropWidth = (int)xPixels;
formatInfo.CropHeight = (int)yPixels;
if (_image._pictureFormat != null && !_image._pictureFormat.IsNull())
{
PictureFormat picFormat = _image.PictureFormat;
//Cropping in pixels.
XUnit cropLeft = picFormat.CropLeft.Point;
XUnit cropRight = picFormat.CropRight.Point;
XUnit cropTop = picFormat.CropTop.Point;
XUnit cropBottom = picFormat.CropBottom.Point;
formatInfo.CropX = (int)(horzRes * cropLeft.Inch);
formatInfo.CropY = (int)(vertRes * cropTop.Inch);
formatInfo.CropWidth -= (int)(horzRes * ((XUnit)(cropLeft + cropRight)).Inch);
formatInfo.CropHeight -= (int)(vertRes * ((XUnit)(cropTop + cropBottom)).Inch);
//Scaled cropping of the height and width.
double xScale = resultWidth / inherentWidth;
double yScale = resultHeight / inherentHeight;
cropLeft = xScale * cropLeft;
cropRight = xScale * cropRight;
cropTop = yScale * cropTop;
cropBottom = yScale * cropBottom;
resultHeight = resultHeight - cropTop - cropBottom;
resultWidth = resultWidth - cropLeft - cropRight;
}
if (resultHeight <= 0 || resultWidth <= 0)
{
formatInfo.Width = XUnit.FromCentimeter(2.5);
formatInfo.Height = XUnit.FromCentimeter(2.5);
Debug.WriteLine(Messages2.EmptyImageSize);
_failure = ImageFailure.EmptySize;
}
else
{
formatInfo.Width = resultWidth;
formatInfo.Height = resultHeight;
}
}
catch (Exception ex)
{
Debug.WriteLine(Messages2.ImageNotReadable(_image.Name, ex.Message));
formatInfo.Failure = ImageFailure.NotRead;
}
finally
{
if (xImage != null)
xImage.Dispose();
}
}
}
if (formatInfo.Failure != ImageFailure.None)
{
if (!_image._width.IsNull)
formatInfo.Width = _image.Width.Point;
else
formatInfo.Width = XUnit.FromCentimeter(2.5);
if (!_image._height.IsNull)
formatInfo.Height = _image.Height.Point;
else
formatInfo.Height = XUnit.FromCentimeter(2.5);
}
}
XImage CreateXImage(string uri)
{
if (uri.StartsWith("base64:"))
{
string base64 = uri.Substring("base64:".Length);
byte[] bytes = Convert.FromBase64String(base64);
#if WPF || CORE_WITH_GDI || GDI
// WPF stores a reference to the stream publicly. We must not destroy the stream here, otherwise rendering the PDF will fail.
// Same for GDI. CORE currently uses the GDI implementation.
// We have to rely on the garbage collector to properly dispose the MemoryStream.
{
Stream stream = new MemoryStream(bytes);
XImage image = XImage.FromStream(stream);
return image;
}
#else
using (Stream stream = new MemoryStream(bytes))
{
XImage image = XImage.FromStream(stream);
return image;
}
#endif
}
return XImage.FromFile(uri);
}
readonly Image _image;
string _imageFilePath;
ImageFailure _failure;
}
}

View File

@@ -0,0 +1,229 @@
#region MigraDoc - Creating Documents on the Fly
//
// Authors:
// Klaus Potzesny
//
// Copyright (c) 2001-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.com
// http://www.migradoc.com
// http://sourceforge.net/projects/pdfsharp
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#endregion
using PdfSharp.Drawing;
namespace MigraDoc.Rendering
{
/// <summary>
/// Abstract base class to serve as a layoutable unit.
/// </summary>
public class LayoutInfo
{
public LayoutInfo()
{ }
/// <summary>
/// Gets or sets the height necessary to start the document object.
/// </summary>
public XUnit StartingHeight
{
get { return _startingHeight; }
set { _startingHeight = value; }
}
XUnit _startingHeight;
/// <summary>
/// Gets or sets the height necessary to end the document object.
/// </summary>
public XUnit TrailingHeight
{
get { return _trailingHeight; }
set { _trailingHeight = value; }
}
XUnit _trailingHeight;
/// <summary>
/// Indicates whether the document object shall be kept on one page
/// with its successor.
/// </summary>
public bool KeepWithNext
{
get { return _keepWithNext; }
set { _keepWithNext = value; }
}
bool _keepWithNext;
/// <summary>
/// Indicates whether the document object shall be kept together on one page.
/// </summary>
public bool KeepTogether
{
get { return _keepTogether; }
set { _keepTogether = value; }
}
bool _keepTogether;
/// <summary>
/// The space that shall be kept free above the element's content.
/// </summary>
public virtual XUnit MarginTop
{
get { return _marginTop; }
set { _marginTop = value; }
}
XUnit _marginTop;
/// <summary>
/// The space that shall be kept free right to the element's content.
/// </summary>
public XUnit MarginRight
{
get { return _marginRight; }
set { _marginRight = value; }
}
XUnit _marginRight;
/// <summary>
/// The space that shall be kept free below the element's content.
/// </summary>
public XUnit MarginBottom
{
get { return _marginBottom; }
set { _marginBottom = value; }
}
XUnit _marginBottom;
/// <summary>
/// The space that shall be kept free left to the element's content.
/// </summary>
public XUnit MarginLeft
{
get { return _marginLeft; }
set { _marginLeft = value; }
}
XUnit _marginLeft;
/// <summary>
/// Gets or sets the Area needed by the content (including padding and borders for e.g. paragraphs).
/// </summary>
public Area ContentArea
{
get { return _contentArea; }
set { _contentArea = value; }
}
Area _contentArea;
/// <summary>
/// Gets or sets the a value indicating whether the element shall appear on a new page.
/// </summary>
public bool PageBreakBefore
{
get { return _pageBreakBefore; }
set { _pageBreakBefore = value; }
}
bool _pageBreakBefore;
/// <summary>
/// Gets or sets the reference point for horizontal positioning.
/// </summary>
/// <remarks>Default value is AreaBoundary.</remarks>
public HorizontalReference HorizontalReference
{
get { return _horizontalReference; }
set { _horizontalReference = value; }
}
HorizontalReference _horizontalReference;
/// <summary>
/// Gets or sets the reference point for vertical positioning.
/// </summary>
/// <remarks>Default value is PreviousElement.</remarks>
public VerticalReference VerticalReference
{
get { return _verticalReference; }
set { _verticalReference = value; }
}
VerticalReference _verticalReference;
/// <summary>
/// Gets or sets the horizontal alignment of the element.
/// </summary>
/// <remarks>Default value is Near.</remarks>
public ElementAlignment HorizontalAlignment
{
get { return _horizontalAlignment; }
set { _horizontalAlignment = value; }
}
ElementAlignment _horizontalAlignment;
/// <summary>
/// Gets or sets the vertical alignment of the element.
/// </summary>
/// <remarks>Default value is Near.</remarks>
public ElementAlignment VerticalAlignment
{
get { return _verticalAlignment; }
set { _verticalAlignment = value; }
}
ElementAlignment _verticalAlignment;
/// <summary>
/// Gets or sets the floating behavior of surrounding elements.
/// </summary>
/// <remarks>Default value is TopBottom.</remarks>
public Floating Floating
{
get { return _floating; }
set { _floating = value; }
}
Floating _floating;
/// <summary>
/// Gets or sets the top position of the element.
/// </summary>
public XUnit Top
{
get { return _top; }
set { _top = value; }
}
XUnit _top;
/// <summary>
/// Gets or sets the left position of the element.
/// </summary>
public XUnit Left
{
get { return _left; }
set { _left = value; }
}
XUnit _left;
/// <summary>
/// Gets or sets the minimum width of the element.
/// </summary>
public XUnit MinWidth
{
get { return _minWidth; }
set { _minWidth = value; }
}
XUnit _minWidth;
}
}

View File

@@ -0,0 +1,122 @@
#region MigraDoc - Creating Documents on the Fly
//
// Authors:
// Klaus Potzesny
//
// Copyright (c) 2001-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.com
// http://www.migradoc.com
// http://sourceforge.net/projects/pdfsharp
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#endregion
using MigraDoc.DocumentObjectModel;
using PdfSharp.Drawing;
using MigraDoc.DocumentObjectModel.Shapes;
namespace MigraDoc.Rendering
{
/// <summary>
/// Renders a line format to an XGraphics object.
/// </summary>
public class LineFormatRenderer
{
public LineFormatRenderer(LineFormat lineFormat, XGraphics gfx)
{
_lineFormat = lineFormat;
_gfx = gfx;
}
private XColor GetColor()
{
Color clr = Colors.Black;
if (_lineFormat != null && !_lineFormat.Color.IsEmpty)
clr = _lineFormat.Color;
#if noCMYK
return XColor.FromArgb((int)clr.Argb);
#else
return ColorHelper.ToXColor(clr, _lineFormat.Document.UseCmykColor);
#endif
}
public XUnit GetWidth()
{
if (_lineFormat == null)
return 0;
if (!_lineFormat._visible.IsNull && !_lineFormat.Visible)
return 0;
if (!_lineFormat._width.IsNull)
return _lineFormat.Width.Point;
if (!_lineFormat._color.IsNull || !_lineFormat._style.IsNull || _lineFormat.Visible)
return 1;
return 0;
}
public void Render(XUnit xPosition, XUnit yPosition, XUnit width, XUnit height)
{
XUnit lineWidth = GetWidth();
if (lineWidth > 0)
{
XPen pen = GetPen(lineWidth);
_gfx.DrawRectangle(pen, xPosition, yPosition, width, height);
}
}
XPen GetPen(XUnit width)
{
if (width == 0)
return null;
XPen pen = new XPen(GetColor(), width);
switch (_lineFormat.DashStyle)
{
case DashStyle.Dash:
pen.DashStyle = XDashStyle.Dash;
break;
case DashStyle.DashDot:
pen.DashStyle = XDashStyle.DashDot;
break;
case DashStyle.DashDotDot:
pen.DashStyle = XDashStyle.DashDotDot;
break;
case DashStyle.Solid:
pen.DashStyle = XDashStyle.Solid;
break;
case DashStyle.SquareDot:
pen.DashStyle = XDashStyle.Dot;
break;
}
return pen;
}
readonly LineFormat _lineFormat;
readonly XGraphics _gfx;
}
}

View File

@@ -0,0 +1,125 @@
#region MigraDoc - Creating Documents on the Fly
//
// Authors:
// Klaus Potzesny
//
// Copyright (c) 2001-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.com
// http://www.migradoc.com
// http://sourceforge.net/projects/pdfsharp
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#endregion
using System;
using System.Diagnostics;
using System.Globalization;
using MigraDoc.Rendering.Resources;
namespace MigraDoc.Rendering
{
/// <summary>
/// Formats numbers roman or with letters.
/// </summary>
public class NumberFormatter
{
public static string Format(int number, string format)
{
switch (format)
{
case "ROMAN":
return AsRoman(number, false);
case "roman":
return AsRoman(number, true);
case "ALPHABETIC":
return AsLetters(number, false);
case "alphabetic":
return AsLetters(number, true);
}
return number.ToString(CultureInfo.InvariantCulture);
}
static string AsRoman(int number, bool lowercase)
{
if (Math.Abs(number) > 32768)
{
Debug.WriteLine(Messages2.NumberTooLargeForRoman(number), "warning");
return number.ToString(CultureInfo.InvariantCulture);
}
if (number == 0)
return "0";
string res = "";
if (number < 0)
res += "-";
number = Math.Abs(number);
string[] roman;
if (lowercase)
roman = new string[] { "m", "cm", "d", "cd", "c", "xc", "l", "xl", "x", "ix", "v", "iv", "i" };
else
roman = new string[] { "M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I" };
int[] numberValues = new int[] { 1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1 };
for (int i = 0; i < numberValues.Length; ++i)
{
while (number >= numberValues[i])
{
res += roman[i];
number -= numberValues[i];
}
}
return res;
}
static string AsLetters(int number, bool lowercase)
{
if (Math.Abs(number) > 32768)
{
Debug.WriteLine(Messages2.NumberTooLargeForLetters(number));
return number.ToString();
}
if (number == 0)
return "0";
string str = "";
if (number < 0)
str += "-";
number = Math.Abs(number);
char cr;
if (lowercase)
cr = (char)('a' + (number - 1) % 26);
else
cr = (char)('A' + (number - 1) % 26);
for (int n = 0; n <= (number - 1) / 26; ++n)
str += cr;
return str;
}
}
}

View File

@@ -0,0 +1,68 @@
#region MigraDoc - Creating Documents on the Fly
//
// Authors:
// Klaus Potzesny
//
// Copyright (c) 2001-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.com
// http://www.migradoc.com
// http://sourceforge.net/projects/pdfsharp
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#endregion
namespace MigraDoc.Rendering
{
/// <summary>
/// Formatting information for a page break.
/// </summary>
public sealed class PageBreakFormatInfo : FormatInfo
{
public override bool EndingIsComplete
{
get { return true; }
}
public override bool IsComplete
{
get { return true; }
}
public override bool IsEmpty
{
get { return false; }
}
public override bool IsEnding
{
get { return true; }
}
public override bool IsStarting
{
get { return true; }
}
public override bool StartingIsComplete
{
get { return true; }
}
}
}

View File

@@ -0,0 +1,63 @@
#region MigraDoc - Creating Documents on the Fly
//
// Authors:
// Klaus Potzesny
//
// Copyright (c) 2001-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.com
// http://www.migradoc.com
// http://sourceforge.net/projects/pdfsharp
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#endregion
using MigraDoc.DocumentObjectModel;
namespace MigraDoc.Rendering
{
/// <summary>
/// Rendering information for page breaks.
/// </summary>
public sealed class PageBreakRenderInfo : RenderInfo
{
public PageBreakRenderInfo()
{ }
/// <summary>
/// Gets the format information in a specific derived type. For a table, for example, this will be a TableFormatInfo with information about the first and last row showing on a page.
/// </summary>
public override FormatInfo FormatInfo
{
get { return _pageBreakFormatInfo; }
set { _pageBreakFormatInfo = (PageBreakFormatInfo)value; }
}
PageBreakFormatInfo _pageBreakFormatInfo;
/// <summary>
/// Gets the document object to which the layout information applies. Use the Tag property of DocumentObject to identify an object.
/// </summary>
public override DocumentObject DocumentObject
{
get { return _pageBreak; }
set { _pageBreak = (PageBreak)value; }
}
PageBreak _pageBreak;
}
}

View File

@@ -0,0 +1,92 @@
#region MigraDoc - Creating Documents on the Fly
//
// Authors:
// Klaus Potzesny
//
// Copyright (c) 2001-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.com
// http://www.migradoc.com
// http://sourceforge.net/projects/pdfsharp
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#endregion
using MigraDoc.DocumentObjectModel;
using PdfSharp.Drawing;
namespace MigraDoc.Rendering
{
/// <summary>
/// Renders a page break to an XGraphics object.
/// </summary>
public class PageBreakRenderer : Renderer
{
/// <summary>
/// Initializes a ParagraphRenderer object for formatting.
/// </summary>
/// <param name="gfx">The XGraphics object to do measurements on.</param>
/// <param name="pageBreak">The page break.</param>
/// <param name="fieldInfos">The field infos.</param>
public PageBreakRenderer(XGraphics gfx, PageBreak pageBreak, FieldInfos fieldInfos)
: base(gfx, pageBreak, fieldInfos)
{
_pageBreak = pageBreak;
}
/// <summary>
/// Initializes a ParagraphRenderer object for rendering.
/// </summary>
/// <param name="gfx">The XGraphics object to render on.</param>
/// <param name="renderInfo">The render info object containing information necessary for rendering.</param>
/// <param name="fieldInfos">The field infos.</param>
public PageBreakRenderer(XGraphics gfx, RenderInfo renderInfo, FieldInfos fieldInfos)
: base(gfx, renderInfo, fieldInfos)
{
_renderInfo = renderInfo;
}
public override void Format(Area area, FormatInfo previousFormatInfo)
{
PageBreakRenderInfo pbRenderInfo = new PageBreakRenderInfo();
pbRenderInfo.FormatInfo = new PageBreakFormatInfo();
_renderInfo = pbRenderInfo;
pbRenderInfo.LayoutInfo.PageBreakBefore = true;
pbRenderInfo.LayoutInfo.ContentArea = new Rectangle(area.Y, area.Y, 0, 0);
pbRenderInfo.DocumentObject = _pageBreak;
}
public override void Render()
{
// Nothing to do here.
}
public override LayoutInfo InitialLayoutInfo
{
get
{
LayoutInfo layoutInfo = new LayoutInfo();
layoutInfo.PageBreakBefore = true;
return layoutInfo;
}
}
readonly PageBreak _pageBreak;
}
}

View File

@@ -0,0 +1,79 @@
#region MigraDoc - Creating Documents on the Fly
//
// Authors:
// Klaus Potzesny
//
// Copyright (c) 2001-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.com
// http://www.migradoc.com
// http://sourceforge.net/projects/pdfsharp
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#endregion
using PdfSharp;
using PdfSharp.Drawing;
namespace MigraDoc.Rendering
{
/// <summary>
/// Provides information necessary to render the page.
/// </summary>
public class PageInfo
{
public PageInfo(XUnit width, XUnit height, PageOrientation orientation)
{
_width = width;
_height = height;
_orientation = orientation;
}
/// <summary>
/// Gets the with of the described page as specified in Document.PageSetup, i.e. the orientation
/// is not taken into account.
/// </summary>
public XUnit Width
{
get { return _width; }
}
private readonly XUnit _width;
/// <summary>
/// Gets the height of the described page as specified in Document.PageSetup, i.e. the orientation
/// is not taken into account.
/// </summary>
public XUnit Height
{
get { return _height; }
}
private readonly XUnit _height;
/// <summary>
/// Gets the orientation of the described page as specified in Document.PageSetup.
/// The value has no influence on the properties Width or Height, i.e. if the result is PageOrientation.Landscape
/// you must exchange the values of Width or Height to get the real page size.
/// </summary>
public PageOrientation Orientation
{
get { return _orientation; }
}
private readonly PageOrientation _orientation;
}
}

View File

@@ -0,0 +1,187 @@
#region MigraDoc - Creating Documents on the Fly
//
// Authors:
// Klaus Potzesny
//
// Copyright (c) 2001-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.com
// http://www.migradoc.com
// http://sourceforge.net/projects/pdfsharp
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#endregion
using System.Collections.Generic;
using MigraDoc.DocumentObjectModel.Shapes;
using PdfSharp.Drawing;
using MigraDoc.DocumentObjectModel;
namespace MigraDoc.Rendering
{
/// <summary>
/// Vertical measurements of a paragraph line.
/// </summary>
public struct VerticalLineInfo
{
public VerticalLineInfo(XUnit height, XUnit descent, XUnit inherentlineSpace)
{
Height = height;
Descent = descent;
InherentlineSpace = inherentlineSpace;
}
public XUnit Height;
public XUnit Descent;
public XUnit InherentlineSpace;
}
/// <summary>
/// Line info object used by the paragraph format info.
/// </summary>
public struct LineInfo
{
public ParagraphIterator StartIter;
public ParagraphIterator EndIter;
public XUnit WordsWidth;
public XUnit LineWidth;
public int BlankCount;
public VerticalLineInfo Vertical;
public List<TabOffset> TabOffsets;
public bool ReMeasureLine;
public DocumentObject LastTab;
}
/// <summary>
/// Formatting information for a paragraph.
/// </summary>
public sealed class ParagraphFormatInfo : FormatInfo
{
public ParagraphFormatInfo()
{ }
public LineInfo GetLineInfo(int lineIdx)
{
return _lineInfos[lineIdx];
}
public LineInfo GetLastLineInfo()
{
return _lineInfos[LineCount - 1];
}
public LineInfo GetFirstLineInfo()
{
return _lineInfos[0];
}
public void AddLineInfo(LineInfo lineInfo)
{
_lineInfos.Add(lineInfo);
}
public int LineCount
{
get { return _lineInfos.Count; }
}
/// <summary>
///
/// </summary>
/// <param name="mergeInfo"></param>
/// <returns></returns>
public void Append(FormatInfo mergeInfo)
{
ParagraphFormatInfo formatInfo = (ParagraphFormatInfo)mergeInfo;
_lineInfos.AddRange(formatInfo._lineInfos);
}
/// <summary>
/// Indicates whether the paragraph is ending.
/// </summary>
/// <returns>True if the paragraph is ending.</returns>
public override bool IsEnding
{
get { return _isEnding; }
}
public bool _isEnding;
/// <summary>
/// Indicates whether the paragraph is starting.
/// </summary>
/// <returns>True if the paragraph is starting.</returns>
public override bool IsStarting
{
get { return _isStarting; }
}
public bool _isStarting;
public override bool IsComplete
{
get { return _isStarting && _isEnding; }
}
public override bool IsEmpty
{
get { return _lineInfos.Count == 0; }
}
public override bool StartingIsComplete
{
get
{
if (_widowControl)
return (IsComplete || (_isStarting && _lineInfos.Count >= 2));
return _isStarting;
}
}
public bool _widowControl;
public override bool EndingIsComplete
{
get
{
if (_widowControl)
return (IsComplete || (_isEnding && _lineInfos.Count >= 2));
return _isEnding;
}
}
public void RemoveEnding()
{
if (!IsEmpty)
{
if (_widowControl && _isEnding && LineCount >= 2)
_lineInfos.RemoveAt(LineCount - 2);
if (LineCount > 0)
_lineInfos.RemoveAt(LineCount - 1);
_isEnding = false;
}
}
public string ListSymbol;
public XFont ListFont;
public Dictionary<Image, RenderInfo> ImageRenderInfos;
readonly List<LineInfo> _lineInfos = new List<LineInfo>();
}
}

View File

@@ -0,0 +1,286 @@
#region MigraDoc - Creating Documents on the Fly
//
// Authors:
// Klaus Potzesny
//
// Copyright (c) 2001-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.com
// http://www.migradoc.com
// http://sourceforge.net/projects/pdfsharp
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#endregion
using System.Collections.Generic;
using MigraDoc.DocumentObjectModel;
namespace MigraDoc.Rendering
{
/// <summary>
/// Iterates sequentially through the elements of a paragraph.
/// </summary>
public class ParagraphIterator
{
/// <summary>
/// Initializes a paragraph iterator pointing on the given paragraph elements object.
/// Paragraph iterators received from this paragraph iterator relate to this root node.
/// </summary>
/// <param name="rootNode">The root node for the paragraph iterator.</param>
public ParagraphIterator(ParagraphElements rootNode)
{
_rootNode = rootNode;
_current = rootNode;
_positionIndices = new List<int>();
}
/// <summary>
/// Initializes a paragraph iterator given the root node, its position in the object tree and the current object
/// </summary>
/// <param name="rootNode">The node the position indices relate to.</param>
/// <param name="current">The element the iterator shall point to.</param>
/// <param name="indices">The position of the paragraph iterator in terms of element indices.</param>
private ParagraphIterator(ParagraphElements rootNode, DocumentObject current, List<int> indices)
{
_rootNode = rootNode;
_positionIndices = indices;
_current = current;
}
/// <summary>
/// Determines whether this iterator is the first leaf of the root node.
/// </summary>
public bool IsFirstLeaf
{
get
{
if (!(_current is DocumentElements))
{
ParagraphIterator prevIter = GetPreviousLeaf();
return prevIter == null;
}
return false;
}
}
/// <summary>
/// Determines whether this iterator is the last leaf of the document object tree.
/// </summary>
public bool IsLastLeaf
{
get
{
if (!(_current is DocumentElements))
{
ParagraphIterator nextIter = GetNextLeaf();
return nextIter == null;
}
return false;
}
}
/// <summary>
/// Gets the document object this instance ponits to.
/// </summary>
public DocumentObject Current
{
get { return _current; }
}
/// <summary>
/// Gets the last leaf of the document object tree.
/// </summary>
/// <returns>The paragraph iterator pointing to the last leaf in the document object tree.</returns>
public ParagraphIterator GetLastLeaf()
{
if (_rootNode.Count == 0)
return null;
return SeekLastLeaf();
}
/// <summary>
/// Gets the first leaf of the element tree.
/// </summary>
/// <returns>The paragraph iterator pointing to the first leaf in the element tree.</returns>
public ParagraphIterator GetFirstLeaf()
{
if (_rootNode.Count == 0)
return null;
return SeekFirstLeaf();
}
/// <summary>
/// Returns the next iterator in the tree pointing to a leaf.
/// </summary>
/// <remarks>This function is intended to receive the renderable objects of a paragraph.
/// Thus, empty ParagraphElement objects (which are collections) don't count as leafs.</remarks>
public ParagraphIterator GetNextLeaf()
{
//Move up to appropriate parent element
ParagraphIterator parIterator = GetParentIterator();
if (parIterator == null)
return null;
int elementIndex = LastIndex;
ParagraphElements parEls = (ParagraphElements)parIterator._current;
while (elementIndex == parEls.Count - 1)
{
elementIndex = parIterator.LastIndex;
parIterator = parIterator.GetParentIterator();
if (parIterator == null)
break;
parEls = (ParagraphElements)parIterator._current;
}
if (parIterator == null)
return null;
int newIndex = elementIndex + 1;
if (newIndex >= parEls.Count)
return null;
List<int> indices = new List<int>(parIterator._positionIndices); //(Array_List)parIterator.positionIndices.Clone();
indices.Add(newIndex);
DocumentObject obj = GetNodeObject(parEls[newIndex]);
ParagraphIterator iterator = new ParagraphIterator(_rootNode, obj, indices);
return iterator.SeekFirstLeaf();
}
/// <summary>
/// Gets the object a paragraph iterator shall point to.
/// Only ParagraphElements and renderable objects are allowed.
/// </summary>
/// <param name="obj">The object to select the node object for.</param>
/// <returns>The object a paragraph iterator shall point to.</returns>
private DocumentObject GetNodeObject(DocumentObject obj)
{
if (obj is FormattedText)
return ((FormattedText)obj).Elements;
if (obj is Hyperlink)
return ((Hyperlink)obj).Elements;
return obj;
}
/// <summary>
/// Returns the previous iterator to a leaf in the document object tree pointing.
/// </summary>
/// <returns>The previous leaf, null if none exists.</returns>
public ParagraphIterator GetPreviousLeaf()
{
//Move up to appropriate parent element
ParagraphIterator parIterator = GetParentIterator();
if (parIterator == null)
return null;
int elementIndex = LastIndex;
ParagraphElements parEls = (ParagraphElements)parIterator._current;
while (elementIndex == 0)
{
elementIndex = parIterator.LastIndex;
parIterator = parIterator.GetParentIterator();
if (parIterator == null)
break;
parEls = (ParagraphElements)parIterator._current;
}
if (parIterator == null)
return null;
int newIndex = elementIndex - 1;
if (newIndex < 0)
return null;
List<int> indices = new List<int>(parIterator._positionIndices);//(Array_List)parIterator.positionIndices.Clone();
indices.Add(newIndex);
DocumentObject obj = GetNodeObject(parEls[newIndex]);
ParagraphIterator iterator = new ParagraphIterator(_rootNode, obj, indices);
return iterator.SeekLastLeaf();
}
private ParagraphIterator SeekLastLeaf()
{
DocumentObject obj = Current;
if (!(obj is ParagraphElements))
return this;
List<int> indices = new List<int>(_positionIndices);
while (obj is ParagraphElements)
{
ParagraphElements parEls = (ParagraphElements)obj;
if (((ParagraphElements)obj).Count == 0)
return new ParagraphIterator(_rootNode, obj, indices);
int idx = ((ParagraphElements)obj).Count - 1;
indices.Add(idx);
obj = GetNodeObject(parEls[idx]);
}
return new ParagraphIterator(_rootNode, obj, indices);
}
/// <summary>
/// Gets the leftmost leaf within the hierarchy.
/// </summary>
/// <returns>The searched leaf.</returns>
ParagraphIterator SeekFirstLeaf()
{
DocumentObject obj = Current;
if (!(obj is ParagraphElements))
return this;
List<int> indices = new List<int>(_positionIndices);
while (obj is ParagraphElements)
{
ParagraphElements parEls = (ParagraphElements)obj;
if (parEls.Count == 0)
return new ParagraphIterator(_rootNode, obj, indices);
indices.Add(0);
obj = GetNodeObject(parEls[0]);
}
return new ParagraphIterator(_rootNode, obj, indices);
}
private ParagraphIterator GetParentIterator()
{
if (_positionIndices.Count == 0)
return null;
List<int> indices = new List<int>(_positionIndices);
indices.RemoveAt(indices.Count - 1);
DocumentObject parent = DocumentRelations.GetParentOfType(_current, typeof(ParagraphElements));
return new ParagraphIterator(_rootNode, parent, indices);
}
private int LastIndex
{
get
{
if (_positionIndices.Count == 0)
return -1;
return _positionIndices[_positionIndices.Count - 1];
}
}
readonly ParagraphElements _rootNode;
readonly List<int> _positionIndices;
readonly DocumentObject _current;
}
}

View File

@@ -0,0 +1,71 @@
#region MigraDoc - Creating Documents on the Fly
//
// Authors:
// Klaus Potzesny
//
// Copyright (c) 2001-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.com
// http://www.migradoc.com
// http://sourceforge.net/projects/pdfsharp
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#endregion
using MigraDoc.DocumentObjectModel;
namespace MigraDoc.Rendering
{
/// <summary>
/// Represents rendering information for a paragraph.
/// </summary>
public sealed class ParagraphRenderInfo : RenderInfo
{
public ParagraphRenderInfo()
{ }
/// <summary>
/// Gets the format information in a specific derived type. For a table, for example, this will be a TableFormatInfo with information about the first and last row showing on a page.
/// </summary>
public override FormatInfo FormatInfo
{
get { return _formatInfo; }
set { _formatInfo = (ParagraphFormatInfo)value; }
}
ParagraphFormatInfo _formatInfo = new ParagraphFormatInfo();
/// <summary>
/// Gets the document object to which the layout information applies. Use the Tag property of DocumentObject to identify an object.
/// </summary>
public override DocumentObject DocumentObject
{
get { return _paragraph; }
set { _paragraph = (Paragraph)value; }
}
Paragraph _paragraph;
public override void RemoveEnding()
{
ParagraphFormatInfo pfInfo = (ParagraphFormatInfo)FormatInfo;
pfInfo.RemoveEnding();
Area contentArea = LayoutInfo.ContentArea;
contentArea.Height -= LayoutInfo.TrailingHeight;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,319 @@
#region MigraDoc - Creating Documents on the Fly
//
// Authors:
// Klaus Potzesny
//
// Copyright (c) 2001-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.com
// http://www.migradoc.com
// http://sourceforge.net/projects/pdfsharp
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#endregion
using System;
using System.Reflection;
using System.IO;
using MigraDoc.DocumentObjectModel;
using MigraDoc.Rendering.Resources;
using PdfSharp.Pdf;
using PdfSharp.Drawing;
namespace MigraDoc.Rendering
{
/// <summary>
/// Provides the functionality to convert a MigraDoc document into PDF.
/// </summary>
public class PdfDocumentRenderer
{
/// <summary>
/// Initializes a new instance of the PdfDocumentRenderer class.
/// </summary>
public PdfDocumentRenderer()
{
//_unicode = true;
}
/// <summary>
/// Initializes a new instance of the <see cref="PdfDocumentRenderer"/> class.
/// </summary>
/// <param name="unicode">If true Unicode encoding is used for all text. If false, WinAnsi encoding is used.</param>
public PdfDocumentRenderer(bool unicode)
{
_unicode = unicode;
}
/// <summary>
/// Initializes a new instance of the <see cref="PdfDocumentRenderer" /> class.
/// </summary>
/// <param name="unicode">If true Unicode encoding is used for all text. If false, WinAnsi encoding is used.</param>
/// <param name="fontEmbedding">Obsolete parameter.</param>
[Obsolete("Must not specify an embedding option anymore.")]
public PdfDocumentRenderer(bool unicode, PdfFontEmbedding fontEmbedding)
{
_unicode = unicode;
}
/// <summary>
/// Gets a value indicating whether the text is rendered as Unicode.
/// </summary>
public bool Unicode
{
get { return _unicode; }
}
readonly bool _unicode;
/// <summary>
/// Gets or sets the language.
/// </summary>
/// <value>The language.</value>
public string Language
{
get { return _language; }
set { _language = value; }
}
string _language = String.Empty;
/// <summary>
/// Set the MigraDoc document to be rendered by this printer.
/// </summary>
public Document Document
{
set
{
_document = null;
value.BindToRenderer(this);
_document = value;
}
}
Document _document;
/// <summary>
/// Gets or sets a document renderer.
/// </summary>
/// <remarks>
/// A document renderer is automatically created and prepared
/// when printing before this property was set.
/// </remarks>
public DocumentRenderer DocumentRenderer
{
get
{
if (_documentRenderer == null)
PrepareDocumentRenderer();
return _documentRenderer;
}
set { _documentRenderer = value; }
}
DocumentRenderer _documentRenderer;
void PrepareDocumentRenderer()
{
PrepareDocumentRenderer(false);
}
void PrepareDocumentRenderer(bool prepareCompletely)
{
if (_document == null)
#if !NETFX_CORE
throw new InvalidOperationException(Messages2.PropertyNotSetBefore("DocumentRenderer", MethodBase.GetCurrentMethod().Name));
#else
throw new InvalidOperationException(Messages2.PropertyNotSetBefore("DocumentRenderer", "PrepareDocumentRenderer"));
#endif
if (_documentRenderer == null)
{
_documentRenderer = new DocumentRenderer(_document);
_documentRenderer.WorkingDirectory = _workingDirectory;
}
if (prepareCompletely && _documentRenderer.FormattedDocument == null)
{
_documentRenderer.PrepareDocument();
}
}
/// <summary>
/// Renders the document into a PdfDocument containing all pages of the document.
/// </summary>
public void RenderDocument()
{
#if true
PrepareRenderPages();
#else
if (this.documentRenderer == null)
PrepareDocumentRenderer();
if (this.pdfDocument == null)
{
this.pdfDocument = new PdfDocument();
this.pdfDocument.Info.Creator = VersionInfo.Creator;
}
WriteDocumentInformation();
#endif
RenderPages(1, _documentRenderer.FormattedDocument.PageCount);
}
/// <summary>
/// Renders the document into a PdfDocument containing all pages of the document.
/// </summary>
public void PrepareRenderPages()
{
//if (this.documentRenderer == null)
PrepareDocumentRenderer(true);
if (_pdfDocument == null)
{
_pdfDocument = CreatePdfDocument();
if (_document.UseCmykColor)
_pdfDocument.Options.ColorMode = PdfColorMode.Cmyk;
}
WriteDocumentInformation();
//RenderPages(1, this.documentRenderer.FormattedDocument.PageCount);
}
/// <summary>
/// Gets the count of pages.
/// </summary>
public int PageCount
{
get { return _documentRenderer.FormattedDocument.PageCount; }
}
/// <summary>
/// Saves the PdfDocument to the specified path. If a file already exists, it will be overwritten.
/// </summary>
public void Save(string path)
{
if (path == null)
throw new ArgumentNullException("path");
if (path == "")
throw new ArgumentException("PDF file Path must not be empty");
if (_workingDirectory != null)
path = Path.Combine(_workingDirectory, path);
_pdfDocument.Save(path);
}
/// <summary>
/// Saves the PDF document to the specified stream.
/// </summary>
public void Save(Stream stream, bool closeStream)
{
_pdfDocument.Save(stream, closeStream);
}
/// <summary>
/// Renders the specified page range.
/// </summary>
/// <param name="startPage">The first page to print.</param>
/// <param name="endPage">The last page to print</param>
public void RenderPages(int startPage, int endPage)
{
if (startPage < 1)
throw new ArgumentOutOfRangeException("startPage");
if (endPage > _documentRenderer.FormattedDocument.PageCount)
throw new ArgumentOutOfRangeException("endPage");
if (_documentRenderer == null)
PrepareDocumentRenderer();
if (_pdfDocument == null)
_pdfDocument = CreatePdfDocument();
_documentRenderer._printDate = DateTime.Now;
for (int pageNr = startPage; pageNr <= endPage; ++pageNr)
{
PdfPage pdfPage = _pdfDocument.AddPage();
PageInfo pageInfo = _documentRenderer.FormattedDocument.GetPageInfo(pageNr);
pdfPage.Width = pageInfo.Width;
pdfPage.Height = pageInfo.Height;
pdfPage.Orientation = pageInfo.Orientation;
using (XGraphics gfx = XGraphics.FromPdfPage(pdfPage))
{
gfx.MUH = _unicode ? PdfFontEncoding.Unicode : PdfFontEncoding.WinAnsi;
_documentRenderer.RenderPage(gfx, pageNr);
}
}
}
/// <summary>
/// Gets or sets a working directory for the printing process.
/// </summary>
public string WorkingDirectory
{
get { return _workingDirectory; }
set { _workingDirectory = value; }
}
string _workingDirectory;
/// <summary>
/// Gets or sets the PDF document to render on.
/// </summary>
/// <remarks>A PDF document in memory is automatically created when printing before this property was set.</remarks>
public PdfDocument PdfDocument
{
get { return _pdfDocument; }
set { _pdfDocument = value; }
}
PdfDocument _pdfDocument;
/// <summary>
/// Writes document information like author and subject to the PDF document.
/// </summary>
public void WriteDocumentInformation()
{
if (!_document.IsNull("Info"))
{
DocumentInfo docInfo = _document.Info;
PdfDocumentInformation pdfInfo = _pdfDocument.Info;
if (!docInfo.IsNull("Author"))
pdfInfo.Author = docInfo.Author;
if (!docInfo.IsNull("Keywords"))
pdfInfo.Keywords = docInfo.Keywords;
if (!docInfo.IsNull("Subject"))
pdfInfo.Subject = docInfo.Subject;
if (!docInfo.IsNull("Title"))
pdfInfo.Title = docInfo.Title;
}
}
/// <summary>
/// Creates a new PDF document.
/// </summary>
PdfDocument CreatePdfDocument()
{
PdfDocument document = new PdfDocument();
document.Info.Creator = "damienbod";
if (!String.IsNullOrEmpty(_language))
document.Language = _language;
return document;
}
}
}

View File

@@ -0,0 +1,207 @@
#region MigraDoc - Creating Documents on the Fly
//
// Authors:
// Klaus Potzesny
//
// Copyright (c) 2001-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.com
// http://www.migradoc.com
// http://sourceforge.net/projects/pdfsharp
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#endregion
#if DELETED
namespace MigraDoc.Rendering
{
/// <summary>
/// Provides the functionality to convert MigraDoc documents into PDF.
/// </summary>
[Obsolete("Use class PdfDocumentRenderer.")] // DELETE: 8/06
public class PdfPrinter
{
/// <summary>
/// Initializes a new instance of the PdfPrinter class.
/// </summary>
public PdfPrinter()
{ }
/// <summary>
/// Set the MigraDoc document to be rendered by this printer.
/// </summary>
public Document Document
{
set
{
_document = null;
value.BindToRenderer(this);
_document = value;
}
}
Document _document;
/// <summary>
/// Gets or sets a document renderer.
/// </summary>
/// <remarks>
/// A document renderer is automatically created and prepared
/// when printing before this property was set.
/// </remarks>
public DocumentRenderer DocumentRenderer
{
get { return _documentRenderer; }
set { _documentRenderer = value; }
}
DocumentRenderer _documentRenderer;
void PrepareDocumentRenderer()
{
if (_document == null)
throw new InvalidOperationException(Messages2.PropertyNotSetBefore("DocumentRenderer", MethodInfo.GetCurrentMethod().Name));
_documentRenderer = new DocumentRenderer(_document);
_documentRenderer.WorkingDirectory = this.workingDirectory;
_documentRenderer.PrepareDocument();
}
/// <summary>
/// Prints a PDF document containing all pages of the document.
/// </summary>
public void PrintDocument()
{
if (_documentRenderer == null)
PrepareDocumentRenderer();
if (_pdfDocument == null)
{
_pdfDocument = new PdfDocument();
_pdfDocument.Info.Creator = VersionInfo.Creator;
}
WriteDocumentInformation();
PrintPages(1, _documentRenderer.FormattedDocument.PageCount);
}
/// <summary>
/// Saves the PDF document to the specified path. If a file already exists, it will be overwritten.
/// </summary>
public void Save(string path)
{
if (path == null)
throw new ArgumentNullException("path");
if (path == "")
throw new ArgumentException("PDF file Path must not be empty");
if (this.workingDirectory != null)
Path.Combine(this.workingDirectory, path);
_pdfDocument.Save(path);
}
/// <summary>
/// Saves the PDF document to the specified stream.
/// </summary>
public void Save(Stream stream, bool closeStream)
{
_pdfDocument.Save(stream, closeStream);
}
/// <summary>
/// Prints the specified page range.
/// </summary>
/// <param name="startPage">The first page to print.</param>
/// <param name="endPage">The last page to print</param>
public void PrintPages(int startPage, int endPage)
{
if (startPage < 1)
throw new ArgumentOutOfRangeException("startPage");
if (endPage > _documentRenderer.FormattedDocument.PageCount)
throw new ArgumentOutOfRangeException("endPage");
if (_documentRenderer == null)
PrepareDocumentRenderer();
if (_pdfDocument == null)
{
_pdfDocument = new PdfDocument();
_pdfDocument.Info.Creator = VersionInfo.Creator;
}
_documentRenderer._printDate = DateTime.Now;
for (int pageNr = startPage; pageNr <= endPage; ++pageNr)
{
PdfPage pdfPage = _pdfDocument.AddPage();
PageInfo pageInfo = _documentRenderer.FormattedDocument.GetPageInfo(pageNr);
pdfPage.Width = pageInfo.Width;
pdfPage.Height = pageInfo.Height;
pdfPage.Orientation = pageInfo.Orientation;
_documentRenderer.RenderPage(XGraphics.FromPdfPage(pdfPage), pageNr);
}
}
/// <summary>
/// Gets or sets a working directory for the printing process.
/// </summary>
public string WorkingDirectory
{
get { return this.workingDirectory; }
set { this.workingDirectory = value; }
}
string workingDirectory;
/// <summary>
/// Gets or sets the PDF document to render on.
/// </summary>
/// <remarks>A PDF document in memory is automatically created when printing before this property was set.</remarks>
public PdfDocument PdfDocument
{
get { return _pdfDocument; }
set { _pdfDocument = value; }
}
/// <summary>
/// Writes document information like author and subject to the PDF document.
/// </summary>
private void WriteDocumentInformation()
{
if (!_document.IsNull("Info"))
{
DocumentInfo docInfo = _document.Info;
PdfDocumentInformation pdfInfo = _pdfDocument.Info;
if (!docInfo.IsNull("Author"))
pdfInfo.Author = docInfo.Author;
if (!docInfo.IsNull("Keywords"))
pdfInfo.Keywords = docInfo.Keywords;
if (!docInfo.IsNull("Subject"))
pdfInfo.Subject = docInfo.Subject;
if (!docInfo.IsNull("Title"))
pdfInfo.Title = docInfo.Title;
}
}
PdfDocument _pdfDocument;
}
}
#endif

View File

@@ -0,0 +1,81 @@
#region MigraDoc - Creating Documents on the Fly
//
// Authors:
// Klaus Potzesny
//
// Copyright (c) 2001-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.com
// http://www.migradoc.com
// http://sourceforge.net/projects/pdfsharp
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#endregion
using MigraDoc.DocumentObjectModel;
using PdfSharp.Drawing;
namespace MigraDoc.Rendering
{
/// <summary>
/// Abstract base class for all classes that store rendering information.
/// </summary>
public abstract class RenderInfo
{
/// <summary>
/// Gets the format information in a specific derived type. For a table, for example, this will be a TableFormatInfo with information about the first and last row showing on a page.
/// </summary>
public abstract FormatInfo FormatInfo { get; set; }
/// <summary>
/// Gets the layout information.
/// </summary>
public LayoutInfo LayoutInfo
{
get { return _layoutInfo; }
}
readonly LayoutInfo _layoutInfo = new LayoutInfo();
/// <summary>
/// Gets the document object to which the layout information applies. Use the Tag property of DocumentObject to identify an object.
/// </summary>
public abstract DocumentObject DocumentObject { get; set; }
public virtual void RemoveEnding()
{
System.Diagnostics.Debug.Assert(false, "Unexpected call of RemoveEnding");
}
public static XUnit GetTotalHeight(RenderInfo[] renderInfos)
{
if (renderInfos == null || renderInfos.Length == 0)
return 0;
int lastIdx = renderInfos.Length - 1;
RenderInfo firstRenderInfo = renderInfos[0];
RenderInfo lastRenderInfo = renderInfos[lastIdx];
LayoutInfo firstLayoutInfo = firstRenderInfo.LayoutInfo;
LayoutInfo lastLayoutInfo = lastRenderInfo.LayoutInfo;
XUnit top = firstLayoutInfo.ContentArea.Y - firstLayoutInfo.MarginTop;
XUnit bottom = lastLayoutInfo.ContentArea.Y + lastLayoutInfo.ContentArea.Height;
bottom += lastLayoutInfo.MarginBottom;
return bottom - top;
}
}
}

View File

@@ -0,0 +1,211 @@
#region MigraDoc - Creating Documents on the Fly
//
// Authors:
// Klaus Potzesny
//
// Copyright (c) 2001-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.com
// http://www.migradoc.com
// http://sourceforge.net/projects/pdfsharp
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#endregion
using MigraDoc.DocumentObjectModel;
using PdfSharp.Drawing;
using MigraDoc.DocumentObjectModel.Tables;
using MigraDoc.DocumentObjectModel.Shapes;
using MigraDoc.DocumentObjectModel.Shapes.Charts;
namespace MigraDoc.Rendering
{
/// <summary>
/// Abstract base class for all renderers.
/// </summary>
public abstract class Renderer
{
/// <summary>
/// Determines the maximum height a single element may have.
/// </summary>
public XUnit MaxElementHeight
{
get { return _maxElementHeight; }
set { _maxElementHeight = value; }
}
public Renderer(XGraphics gfx, DocumentObject documentObject, FieldInfos fieldInfos)
{
_documentObject = documentObject;
_gfx = gfx;
_fieldInfos = fieldInfos;
}
public Renderer(XGraphics gfx, RenderInfo renderInfo, FieldInfos fieldInfos)
{
_documentObject = renderInfo.DocumentObject;
_gfx = gfx;
_renderInfo = renderInfo;
_fieldInfos = fieldInfos;
}
/// <summary>
/// In inherited classes, gets a layout info with only margin and break information set.
/// It can be taken before the documen object is formatted.
/// </summary>
/// <remarks>
/// In inherited classes, the following parts are set properly:
/// MarginTop, MarginLeft, MarginRight, MarginBottom,
/// KeepTogether, KeepWithNext, PagebreakBefore, Floating,
/// VerticalReference, HorizontalReference.
/// </remarks>
public abstract LayoutInfo InitialLayoutInfo { get; }
/// <summary>
/// Renders the contents shifted to the given Coordinates.
/// </summary>
/// <param name="xShift">The x shift.</param>
/// <param name="yShift">The y shift.</param>
/// <param name="renderInfos">The render infos.</param>
protected void RenderByInfos(XUnit xShift, XUnit yShift, RenderInfo[] renderInfos)
{
if (renderInfos == null)
return;
foreach (RenderInfo renderInfo in renderInfos)
{
XUnit savedX = renderInfo.LayoutInfo.ContentArea.X;
XUnit savedY = renderInfo.LayoutInfo.ContentArea.Y;
renderInfo.LayoutInfo.ContentArea.X += xShift;
renderInfo.LayoutInfo.ContentArea.Y += yShift;
Renderer renderer = Create(_gfx, _documentRenderer, renderInfo, _fieldInfos);
renderer.Render();
renderInfo.LayoutInfo.ContentArea.X = savedX;
renderInfo.LayoutInfo.ContentArea.Y = savedY;
}
}
protected void RenderByInfos(RenderInfo[] renderInfos)
{
RenderByInfos(0, 0, renderInfos);
}
/// <summary>
/// Gets the render information necessary to render and position the object.
/// </summary>
public RenderInfo RenderInfo
{
get { return _renderInfo; }
}
protected RenderInfo _renderInfo;
/// <summary>
/// Sets the field infos object.
/// </summary>
/// <remarks>This property is set by the AreaProvider.</remarks>
public FieldInfos FieldInfos
{
set { _fieldInfos = value; }
}
protected FieldInfos _fieldInfos;
/// <summary>
/// Renders (draws) the object to the Graphics object.
/// </summary>
public abstract void Render();
/// <summary>
/// Formats the object by calculating distances and linebreaks and stopping when the area is filled.
/// </summary>
/// <param name="area">The area to render into.</param>
/// <param name="previousFormatInfo">An information object received from a previous call of Format().
/// Null for the first call.</param>
public abstract void Format(Area area, FormatInfo previousFormatInfo);
/// <summary>
/// Creates a fitting renderer for the given document object for formatting.
/// </summary>
/// <param name="gfx">The XGraphics object to do measurements on.</param>
/// <param name="documentRenderer">The document renderer.</param>
/// <param name="documentObject">the document object to format.</param>
/// <param name="fieldInfos">The field infos.</param>
/// <returns>The fitting Renderer.</returns>
public static Renderer Create(XGraphics gfx, DocumentRenderer documentRenderer, DocumentObject documentObject, FieldInfos fieldInfos)
{
Renderer renderer = null;
if (documentObject is Paragraph)
renderer = new ParagraphRenderer(gfx, (Paragraph)documentObject, fieldInfos);
else if (documentObject is Table)
renderer = new TableRenderer(gfx, (Table)documentObject, fieldInfos);
else if (documentObject is PageBreak)
renderer = new PageBreakRenderer(gfx, (PageBreak)documentObject, fieldInfos);
else if (documentObject is TextFrame)
renderer = new TextFrameRenderer(gfx, (TextFrame)documentObject, fieldInfos);
else if (documentObject is Chart)
renderer = new ChartRenderer(gfx, (Chart)documentObject, fieldInfos);
else if (documentObject is Image)
renderer = new ImageRenderer(gfx, (Image)documentObject, fieldInfos);
if (renderer != null)
renderer._documentRenderer = documentRenderer;
return renderer;
}
/// <summary>
/// Creates a fitting renderer for the render info to render and layout with.
/// </summary>
/// <param name="gfx">The XGraphics object to render on.</param>
/// <param name="documentRenderer">The document renderer.</param>
/// <param name="renderInfo">The RenderInfo object stored after a previous call of Format().</param>
/// <param name="fieldInfos">The field infos.</param>
/// <returns>The fitting Renderer.</returns>
public static Renderer Create(XGraphics gfx, DocumentRenderer documentRenderer, RenderInfo renderInfo, FieldInfos fieldInfos)
{
Renderer renderer = null;
if (renderInfo.DocumentObject is Paragraph)
renderer = new ParagraphRenderer(gfx, renderInfo, fieldInfos);
else if (renderInfo.DocumentObject is Table)
renderer = new TableRenderer(gfx, renderInfo, fieldInfos);
else if (renderInfo.DocumentObject is PageBreak)
renderer = new PageBreakRenderer(gfx, renderInfo, fieldInfos);
else if (renderInfo.DocumentObject is TextFrame)
renderer = new TextFrameRenderer(gfx, renderInfo, fieldInfos);
else if (renderInfo.DocumentObject is Chart)
renderer = new ChartRenderer(gfx, renderInfo, fieldInfos);
//else if (renderInfo.DocumentObject is Chart)
// renderer = new ChartRenderer(gfx, renderInfo, fieldInfos);
else if (renderInfo.DocumentObject is Image)
renderer = new ImageRenderer(gfx, renderInfo, fieldInfos);
if (renderer != null)
renderer._documentRenderer = documentRenderer;
return renderer;
}
public readonly static XUnit Tolerance = XUnit.FromPoint(0.001);
private XUnit _maxElementHeight = -1;
protected DocumentObject _documentObject;
protected DocumentRenderer _documentRenderer;
protected XGraphics _gfx;
}
}

View File

@@ -0,0 +1,120 @@
#region MigraDoc - Creating Documents on the Fly
//
// Authors:
// Klaus Potzesny
//
// Copyright (c) 2001-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.com
// http://www.migradoc.com
// http://sourceforge.net/projects/pdfsharp
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#endregion
using MigraDoc.DocumentObjectModel.Tables;
using PdfSharp.Drawing;
using MigraDoc.DocumentObjectModel;
namespace MigraDoc.Rendering
{
/// <summary>
/// Renders a Shading to an XGraphics object.
/// </summary>
public class ShadingRenderer
{
public ShadingRenderer(XGraphics gfx, Shading shading)
{
_gfx = gfx;
_shading = shading;
RealizeBrush();
}
public void Render(XUnit x, XUnit y, XUnit width, XUnit height)
{
if (_shading == null || _brush == null)
return;
_gfx.DrawRectangle(_brush, x.Point, y.Point, width.Point, height.Point);
}
public void Render(XUnit x, XUnit y, XUnit width, XUnit height, RoundedCorner roundedCorner)
{
// If there is no rounded corner, we can use the usual Render method.
if (roundedCorner == RoundedCorner.None)
{
Render(x, y, width, height);
return;
}
if (_shading == null || _brush == null)
return;
XGraphicsPath path = new XGraphicsPath();
switch (roundedCorner)
{
case RoundedCorner.TopLeft:
path.AddArc(new XRect(x, y, width * 2, height * 2), 180, 90); // Error in CORE: _corePath.AddArc().
path.AddLine(new XPoint(x + width, y), new XPoint(x + width, y + height));
break;
case RoundedCorner.TopRight:
path.AddArc(new XRect(x - width, y, width * 2, height * 2), 270, 90); // Error in CORE: _corePath.AddArc().
path.AddLine(new XPoint(x + width, y + height), new XPoint(x, y + height));
break;
case RoundedCorner.BottomRight:
path.AddArc(new XRect(x - width, y - height, width * 2, height * 2), 0, 90); // Error in CORE: _corePath.AddArc().
path.AddLine(new XPoint(x, y + height), new XPoint(x, y));
break;
case RoundedCorner.BottomLeft:
path.AddArc(new XRect(x, y - height, width * 2, height * 2), 90, 90); // Error in CORE: _corePath.AddArc().
path.AddLine(new XPoint(x, y), new XPoint(x + width, y));
break;
}
path.CloseFigure();
_gfx.DrawPath(_brush, path);
}
private bool IsVisible()
{
if (!_shading._visible.IsNull)
return _shading.Visible;
else
return !_shading._color.IsNull;
}
private void RealizeBrush()
{
if (_shading == null)
return;
if (IsVisible())
{
#if noCMYK
this.brush = new XSolidBrush(XColor.FromArgb((int)this.shading.Color.Argb));
#else
_brush = new XSolidBrush(ColorHelper.ToXColor(_shading.Color, _shading.Document.UseCmykColor));
#endif
}
}
readonly Shading _shading;
XBrush _brush;
readonly XGraphics _gfx;
}
}

View File

@@ -0,0 +1,77 @@
#region MigraDoc - Creating Documents on the Fly
//
// Authors:
// Klaus Potzesny
//
// Copyright (c) 2001-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.com
// http://www.migradoc.com
// http://sourceforge.net/projects/pdfsharp
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#endregion
namespace MigraDoc.Rendering
{
/// <summary>
/// Format information for all shapes.
/// </summary>
public
class ShapeFormatInfo : FormatInfo
{
public override bool IsStarting
{
get { return Fits; }
}
public override bool IsEnding
{
get { return Fits; }
}
public override bool IsComplete
{
get { return Fits; }
}
/// <summary>
/// Indicates that the starting of the element is completed
/// </summary>
public override bool StartingIsComplete
{
get { return Fits; }
}
/// <summary>
/// Indicates that the ending of the element is completed
/// </summary>
public override bool EndingIsComplete
{
get { return Fits; }
}
public override bool IsEmpty
{
get { return !Fits; }
}
public bool Fits;
}
}

View File

@@ -0,0 +1,54 @@
#region MigraDoc - Creating Documents on the Fly
//
// Authors:
// Klaus Potzesny
//
// Copyright (c) 2001-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.com
// http://www.migradoc.com
// http://sourceforge.net/projects/pdfsharp
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#endregion
using MigraDoc.DocumentObjectModel;
using MigraDoc.DocumentObjectModel.Shapes;
namespace MigraDoc.Rendering
{
/// <summary>
/// Rendering information for shapes.
/// </summary>
public abstract class ShapeRenderInfo : RenderInfo
{
public ShapeRenderInfo()
{ }
/// <summary>
/// Gets the document object to which the layout information applies. Use the Tag property of DocumentObject to identify an object.
/// </summary>
public override DocumentObject DocumentObject
{
get { return _shape; }
set { _shape = (Shape)value; }
}
Shape _shape;
}
}

View File

@@ -0,0 +1,234 @@
#region MigraDoc - Creating Documents on the Fly
//
// Authors:
// Klaus Potzesny
//
// Copyright (c) 2001-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.com
// http://www.migradoc.com
// http://sourceforge.net/projects/pdfsharp
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#endregion
using System;
using PdfSharp.Drawing;
using MigraDoc.DocumentObjectModel.Shapes;
using MigraDoc.DocumentObjectModel.publics;
namespace MigraDoc.Rendering
{
/// <summary>
/// Renders a shape to an XGraphics object.
/// </summary>
public abstract class ShapeRenderer : Renderer
{
public ShapeRenderer(XGraphics gfx, Shape shape, FieldInfos fieldInfos)
: base(gfx, shape, fieldInfos)
{
_shape = shape;
LineFormat lf = (LineFormat)_shape.GetValue("LineFormat", GV.ReadOnly);
_lineFormatRenderer = new LineFormatRenderer(lf, gfx);
}
public ShapeRenderer(XGraphics gfx, RenderInfo renderInfo, FieldInfos fieldInfos)
: base(gfx, renderInfo, fieldInfos)
{
_shape = (Shape)renderInfo.DocumentObject;
LineFormat lf = (LineFormat)_shape.GetValue("LineFormat", GV.ReadOnly);
_lineFormatRenderer = new LineFormatRenderer(lf, gfx);
FillFormat ff = (FillFormat)_shape.GetValue("FillFormat", GV.ReadOnly);
_fillFormatRenderer = new FillFormatRenderer(ff, gfx);
}
public override LayoutInfo InitialLayoutInfo
{
get
{
LayoutInfo layoutInfo = new LayoutInfo();
layoutInfo.MarginTop = _shape.WrapFormat.DistanceTop.Point;
layoutInfo.MarginLeft = _shape.WrapFormat.DistanceLeft.Point;
layoutInfo.MarginBottom = _shape.WrapFormat.DistanceBottom.Point;
layoutInfo.MarginRight = _shape.WrapFormat.DistanceRight.Point;
layoutInfo.KeepTogether = true;
layoutInfo.KeepWithNext = false;
layoutInfo.PageBreakBefore = false;
layoutInfo.VerticalReference = GetVerticalReference();
layoutInfo.HorizontalReference = GetHorizontalReference();
layoutInfo.Floating = GetFloating();
if (layoutInfo.Floating == Floating.TopBottom && !_shape.Top.Position.IsEmpty)
layoutInfo.MarginTop = Math.Max(layoutInfo.MarginTop, _shape.Top.Position);
return layoutInfo;
}
}
Floating GetFloating()
{
if (_shape.RelativeVertical != RelativeVertical.Line && _shape.RelativeVertical != RelativeVertical.Paragraph)
return Floating.None;
switch (_shape.WrapFormat.Style)
{
case WrapStyle.None:
case WrapStyle.Through:
return Floating.None;
}
return Floating.TopBottom;
}
/// <summary>
/// Gets the shape width including line width.
/// </summary>
protected virtual XUnit ShapeWidth
{
get { return _shape.Width + _lineFormatRenderer.GetWidth(); }
}
/// <summary>
/// Gets the shape height including line width.
/// </summary>
protected virtual XUnit ShapeHeight
{
get { return _shape.Height + _lineFormatRenderer.GetWidth(); }
}
/// <summary>
/// Formats the shape.
/// </summary>
/// <param name="area">The area to fit in the shape.</param>
/// <param name="previousFormatInfo"></param>
public override void Format(Area area, FormatInfo previousFormatInfo)
{
Floating floating = GetFloating();
bool fits = floating == Floating.None || ShapeHeight <= area.Height;
((ShapeFormatInfo)_renderInfo.FormatInfo).Fits = fits;
FinishLayoutInfo(area);
}
void FinishLayoutInfo(Area area)
{
LayoutInfo layoutInfo = _renderInfo.LayoutInfo;
Area contentArea = new Rectangle(area.X, area.Y, ShapeWidth, ShapeHeight);
layoutInfo.ContentArea = contentArea;
layoutInfo.MarginTop = _shape.WrapFormat.DistanceTop.Point;
layoutInfo.MarginLeft = _shape.WrapFormat.DistanceLeft.Point;
layoutInfo.MarginBottom = _shape.WrapFormat.DistanceBottom.Point;
layoutInfo.MarginRight = _shape.WrapFormat.DistanceRight.Point;
layoutInfo.KeepTogether = true;
layoutInfo.KeepWithNext = false;
layoutInfo.PageBreakBefore = false;
layoutInfo.MinWidth = ShapeWidth;
if (_shape.Top.ShapePosition == ShapePosition.Undefined)
layoutInfo.Top = _shape.Top.Position.Point;
layoutInfo.VerticalAlignment = GetVerticalAlignment();
layoutInfo.HorizontalAlignment = GetHorizontalAlignment();
if (_shape.Left.ShapePosition == ShapePosition.Undefined)
layoutInfo.Left = _shape.Left.Position.Point;
layoutInfo.HorizontalReference = GetHorizontalReference();
layoutInfo.VerticalReference = GetVerticalReference();
layoutInfo.Floating = GetFloating();
}
HorizontalReference GetHorizontalReference()
{
switch (_shape.RelativeHorizontal)
{
case RelativeHorizontal.Margin:
return HorizontalReference.PageMargin;
case RelativeHorizontal.Page:
return HorizontalReference.Page;
}
return HorizontalReference.AreaBoundary;
}
VerticalReference GetVerticalReference()
{
switch (_shape.RelativeVertical)
{
case RelativeVertical.Margin:
return VerticalReference.PageMargin;
case RelativeVertical.Page:
return VerticalReference.Page;
}
return VerticalReference.PreviousElement;
}
ElementAlignment GetVerticalAlignment()
{
switch (_shape.Top.ShapePosition)
{
case ShapePosition.Center:
return ElementAlignment.Center;
case ShapePosition.Bottom:
return ElementAlignment.Far;
}
return ElementAlignment.Near;
}
protected void RenderFilling()
{
Area contentArea = _renderInfo.LayoutInfo.ContentArea;
XUnit lineWidth = _lineFormatRenderer.GetWidth();
// Half of the line is drawn outside the shape, the other half inside the shape.
// Therefore we have to reduce the position of the filling by 0.5 lineWidth and width and height by 2 lineWidth.
_fillFormatRenderer.Render(contentArea.X + lineWidth / 2, contentArea.Y + lineWidth / 2,
contentArea.Width - 2 * lineWidth, contentArea.Height - 2 * lineWidth);
}
protected void RenderLine()
{
Area contentArea = _renderInfo.LayoutInfo.ContentArea;
XUnit lineWidth = _lineFormatRenderer.GetWidth();
XUnit width = contentArea.Width - lineWidth;
XUnit height = contentArea.Height - lineWidth;
_lineFormatRenderer.Render(contentArea.X, contentArea.Y, width, height);
}
ElementAlignment GetHorizontalAlignment()
{
switch (_shape.Left.ShapePosition)
{
case ShapePosition.Center:
return ElementAlignment.Center;
case ShapePosition.Right:
return ElementAlignment.Far;
case ShapePosition.Outside:
return ElementAlignment.Outside;
case ShapePosition.Inside:
return ElementAlignment.Inside;
}
return ElementAlignment.Near;
}
protected LineFormatRenderer _lineFormatRenderer;
protected FillFormatRenderer _fillFormatRenderer;
protected Shape _shape;
}
}

View File

@@ -0,0 +1,98 @@
#region MigraDoc - Creating Documents on the Fly
//
// Authors:
// Klaus Potzesny
//
// Copyright (c) 2001-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.com
// http://www.migradoc.com
// http://sourceforge.net/projects/pdfsharp
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#endregion
using System.Collections.Generic;
using MigraDoc.DocumentObjectModel.Tables;
using MigraDoc.DocumentObjectModel.Visitors;
using PdfSharp.Drawing;
namespace MigraDoc.Rendering
{
/// <summary>
/// Formatting information for tables.
/// </summary>
public class TableFormatInfo : FormatInfo
{
public TableFormatInfo()
{ }
public override bool EndingIsComplete
{
get { return _isEnding; }
}
public override bool StartingIsComplete
{
get { return !IsEmpty && StartRow > LastHeaderRow; }
}
public override bool IsComplete
{
get { return false; }
}
public override bool IsEmpty
{
get { return StartRow < 0; }
}
public override bool IsEnding
{
get { return _isEnding; }
}
public bool _isEnding;
public override bool IsStarting
{
get { return StartRow == LastHeaderRow + 1; }
}
public int StartColumn = -1;
public int EndColumn = -1;
/// <summary>
/// The first row of the table that is showing on a page.
/// </summary>
public int StartRow = -1;
/// <summary>
/// The last row of the table that is showing on a page.
/// </summary>
public int EndRow = -1;
public int LastHeaderRow = -1;
/// <summary>
/// The formatted cells.
/// </summary>
public Dictionary<Cell, FormattedCell> FormattedCells; //Sorted_List formattedCells;
public MergedCellList MergedCells;
public Dictionary<int, XUnit> BottomBorderMap; //Sorted_List bottomBorderMap;
public Dictionary<int, int> ConnectedRowsMap; //Sorted_List connectedRowsMap;
}
}

View File

@@ -0,0 +1,64 @@
#region MigraDoc - Creating Documents on the Fly
//
// Authors:
// Klaus Potzesny
//
// Copyright (c) 2001-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.com
// http://www.migradoc.com
// http://sourceforge.net/projects/pdfsharp
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#endregion
using MigraDoc.DocumentObjectModel;
using MigraDoc.DocumentObjectModel.Tables;
namespace MigraDoc.Rendering
{
/// <summary>
/// Rendering information for tables.
/// </summary>
public class TableRenderInfo : RenderInfo
{
public TableRenderInfo()
{ }
/// <summary>
/// Gets the format information in a specific derived type. For a table, for example, this will be a TableFormatInfo with information about the first and last row showing on a page.
/// </summary>
public override FormatInfo FormatInfo
{
get { return _formatInfo; }
set { _formatInfo = (TableFormatInfo)value; }
}
TableFormatInfo _formatInfo = new TableFormatInfo();
/// <summary>
/// Gets the document object to which the layout information applies. Use the Tag property of DocumentObject to identify an object.
/// </summary>
public override DocumentObject DocumentObject
{
get { return _table; }
set { _table = (Table)value; }
}
Table _table;
}
}

View File

@@ -0,0 +1,821 @@
#region MigraDoc - Creating Documents on the Fly
//
// Authors:
// Klaus Potzesny
//
// Copyright (c) 2001-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.com
// http://www.migradoc.com
// http://sourceforge.net/projects/pdfsharp
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#endregion
using System;
using System.Collections.Generic;
using MigraDoc.DocumentObjectModel.publics;
using PdfSharp.Drawing;
using MigraDoc.DocumentObjectModel;
using MigraDoc.DocumentObjectModel.Visitors;
using MigraDoc.DocumentObjectModel.Tables;
namespace MigraDoc.Rendering
{
/// <summary>
/// Renders a table to an XGraphics object.
/// </summary>
public class TableRenderer : Renderer
{
public TableRenderer(XGraphics gfx, Table documentObject, FieldInfos fieldInfos)
: base(gfx, documentObject, fieldInfos)
{
_table = documentObject;
}
public TableRenderer(XGraphics gfx, RenderInfo renderInfo, FieldInfos fieldInfos)
: base(gfx, renderInfo, fieldInfos)
{
_table = (Table)_renderInfo.DocumentObject;
}
public override LayoutInfo InitialLayoutInfo
{
get
{
LayoutInfo layoutInfo = new LayoutInfo();
layoutInfo.KeepTogether = _table.KeepTogether;
layoutInfo.KeepWithNext = false;
layoutInfo.MarginBottom = 0;
layoutInfo.MarginLeft = 0;
layoutInfo.MarginTop = 0;
layoutInfo.MarginRight = 0;
return layoutInfo;
}
}
private void InitRendering()
{
TableFormatInfo formatInfo = (TableFormatInfo)_renderInfo.FormatInfo;
_bottomBorderMap = formatInfo.BottomBorderMap;
_connectedRowsMap = formatInfo.ConnectedRowsMap;
_formattedCells = formatInfo.FormattedCells;
_currRow = formatInfo.StartRow;
_startRow = formatInfo.StartRow;
_endRow = formatInfo.EndRow;
_mergedCells = formatInfo.MergedCells;
_lastHeaderRow = formatInfo.LastHeaderRow;
_startX = _renderInfo.LayoutInfo.ContentArea.X;
_startY = _renderInfo.LayoutInfo.ContentArea.Y;
}
private void RenderHeaderRows()
{
if (_lastHeaderRow < 0)
return;
foreach (Cell cell in _mergedCells)
{
if (cell.Row.Index <= _lastHeaderRow)
RenderCell(cell);
}
}
private void RenderCell(Cell cell)
{
Rectangle innerRect = GetInnerRect(CalcStartingHeight(), cell);
RenderShading(cell, innerRect);
RenderContent(cell, innerRect);
RenderBorders(cell, innerRect);
}
private void EqualizeRoundedCornerBorders(Cell cell)
{
// If any of a corner relevant border is set, we want to copy its values to the second corner relevant border,
// to ensure the innerWidth of the cell is the same, regardless of which border is used.
// If set, we use the vertical borders as source for the values, otherwise we use the horizontal borders.
RoundedCorner roundedCorner = cell.RoundedCorner;
if (roundedCorner == RoundedCorner.None)
return;
BorderType primaryBorderType = BorderType.Top, secondaryBorderType = BorderType.Top;
if (roundedCorner == RoundedCorner.TopLeft || roundedCorner == RoundedCorner.BottomLeft)
primaryBorderType = BorderType.Left;
if (roundedCorner == RoundedCorner.TopRight || roundedCorner == RoundedCorner.BottomRight)
primaryBorderType = BorderType.Right;
if (roundedCorner == RoundedCorner.TopLeft || roundedCorner == RoundedCorner.TopRight)
secondaryBorderType = BorderType.Top;
if (roundedCorner == RoundedCorner.BottomLeft || roundedCorner == RoundedCorner.BottomRight)
secondaryBorderType = BorderType.Bottom;
// If both borders don't exist, there's nothing to do and we should not create one by accessing it.
if (!cell.Borders.HasBorder(primaryBorderType) && !cell.Borders.HasBorder(secondaryBorderType))
return;
// Get the borders. By using GV.ReadWrite we create the border, if not existing.
Border primaryBorder = (Border)cell.Borders.GetValue(primaryBorderType.ToString(), GV.ReadWrite);
Border secondaryBorder = (Border)cell.Borders.GetValue(secondaryBorderType.ToString(), GV.ReadWrite);
Border source = primaryBorder.Visible ? primaryBorder
: secondaryBorder.Visible ? secondaryBorder : null;
Border target = primaryBorder.Visible ? secondaryBorder
: secondaryBorder.Visible ? primaryBorder : null;
if (source == null || target == null)
return;
target.Visible = source.Visible;
target.Width = source.Width;
target.Style = source.Style;
target.Color = source.Color;
}
private void RenderShading(Cell cell, Rectangle innerRect)
{
ShadingRenderer shadeRenderer = new ShadingRenderer(_gfx, cell.Shading);
shadeRenderer.Render(innerRect.X, innerRect.Y, innerRect.Width, innerRect.Height, cell.RoundedCorner);
}
private void RenderBorders(Cell cell, Rectangle innerRect)
{
XUnit leftPos = innerRect.X;
XUnit rightPos = leftPos + innerRect.Width;
XUnit topPos = innerRect.Y;
XUnit bottomPos = innerRect.Y + innerRect.Height;
Borders mergedBorders = _mergedCells.GetEffectiveBorders(cell);
BordersRenderer bordersRenderer = new BordersRenderer(mergedBorders, _gfx);
XUnit bottomWidth = bordersRenderer.GetWidth(BorderType.Bottom);
XUnit leftWidth = bordersRenderer.GetWidth(BorderType.Left);
XUnit topWidth = bordersRenderer.GetWidth(BorderType.Top);
XUnit rightWidth = bordersRenderer.GetWidth(BorderType.Right);
if (cell.RoundedCorner == RoundedCorner.TopLeft)
bordersRenderer.RenderRounded(cell.RoundedCorner, innerRect.X, innerRect.Y, innerRect.Width + rightWidth, innerRect.Height + bottomWidth);
else if (cell.RoundedCorner == RoundedCorner.TopRight)
bordersRenderer.RenderRounded(cell.RoundedCorner, innerRect.X - leftWidth, innerRect.Y, innerRect.Width + leftWidth, innerRect.Height + bottomWidth);
else if (cell.RoundedCorner == RoundedCorner.BottomLeft)
bordersRenderer.RenderRounded(cell.RoundedCorner, innerRect.X, innerRect.Y - topWidth, innerRect.Width + rightWidth, innerRect.Height + topWidth);
else if (cell.RoundedCorner == RoundedCorner.BottomRight)
bordersRenderer.RenderRounded(cell.RoundedCorner, innerRect.X - leftWidth, innerRect.Y - topWidth, innerRect.Width + leftWidth, innerRect.Height + topWidth);
// Render horizontal and vertical borders only if touching no rounded corner.
if (cell.RoundedCorner != RoundedCorner.TopRight && cell.RoundedCorner != RoundedCorner.BottomRight)
bordersRenderer.RenderVertically(BorderType.Right, rightPos, topPos, bottomPos + bottomWidth - topPos);
if (cell.RoundedCorner != RoundedCorner.TopLeft && cell.RoundedCorner != RoundedCorner.BottomLeft)
bordersRenderer.RenderVertically(BorderType.Left, leftPos - leftWidth, topPos, bottomPos + bottomWidth - topPos);
if (cell.RoundedCorner != RoundedCorner.BottomLeft && cell.RoundedCorner != RoundedCorner.BottomRight)
bordersRenderer.RenderHorizontally(BorderType.Bottom, leftPos - leftWidth, bottomPos, rightPos + rightWidth + leftWidth - leftPos);
if (cell.RoundedCorner != RoundedCorner.TopLeft && cell.RoundedCorner != RoundedCorner.TopRight)
bordersRenderer.RenderHorizontally(BorderType.Top, leftPos - leftWidth, topPos - topWidth, rightPos + rightWidth + leftWidth - leftPos);
RenderDiagonalBorders(mergedBorders, innerRect);
}
private void RenderDiagonalBorders(Borders mergedBorders, Rectangle innerRect)
{
BordersRenderer bordersRenderer = new BordersRenderer(mergedBorders, _gfx);
bordersRenderer.RenderDiagonally(BorderType.DiagonalDown, innerRect.X, innerRect.Y, innerRect.Width, innerRect.Height);
bordersRenderer.RenderDiagonally(BorderType.DiagonalUp, innerRect.X, innerRect.Y, innerRect.Width, innerRect.Height);
}
private void RenderContent(Cell cell, Rectangle innerRect)
{
FormattedCell formattedCell = _formattedCells[cell];
RenderInfo[] renderInfos = formattedCell.GetRenderInfos();
if (renderInfos == null)
return;
VerticalAlignment verticalAlignment = cell.VerticalAlignment;
XUnit contentHeight = formattedCell.ContentHeight;
XUnit innerHeight = innerRect.Height;
XUnit targetX = innerRect.X + cell.Column.LeftPadding;
XUnit targetY;
if (verticalAlignment == VerticalAlignment.Bottom)
{
targetY = innerRect.Y + innerRect.Height;
targetY -= cell.Row.BottomPadding;
targetY -= contentHeight;
}
else if (verticalAlignment == VerticalAlignment.Center)
{
targetY = innerRect.Y + cell.Row.TopPadding;
targetY += innerRect.Y + innerRect.Height - cell.Row.BottomPadding;
targetY -= contentHeight;
targetY /= 2;
}
else
targetY = innerRect.Y + cell.Row.TopPadding;
RenderByInfos(targetX, targetY, renderInfos);
}
private Rectangle GetInnerRect(XUnit startingHeight, Cell cell)
{
BordersRenderer bordersRenderer = new BordersRenderer(_mergedCells.GetEffectiveBorders(cell), _gfx);
FormattedCell formattedCell = _formattedCells[cell];
XUnit width = formattedCell.InnerWidth;
XUnit y = _startY;
if (cell.Row.Index > _lastHeaderRow)
y += startingHeight;
else
y += CalcMaxTopBorderWidth(0);
#if true
// !!!new 18-03-09 Attempt to fix an exception. begin
XUnit upperBorderPos;
if (!_bottomBorderMap.TryGetValue(cell.Row.Index, out upperBorderPos))
{
//GetType();
}
// !!!new 18-03-09 Attempt to fix an exception. end
#else
XUnit upperBorderPos = _bottomBorderMap[cell.Row.Index];
#endif
y += upperBorderPos;
if (cell.Row.Index > _lastHeaderRow)
y -= _bottomBorderMap[_startRow];
#if true
// !!!new 18-03-09 Attempt to fix an exception. begin
XUnit lowerBorderPos;
if (!_bottomBorderMap.TryGetValue(cell.Row.Index + cell.MergeDown + 1, out lowerBorderPos))
{
//GetType();
}
// !!!new 18-03-09 Attempt to fix an exception. end
#else
XUnit lowerBorderPos = _bottomBorderMap[cell.Row.Index + cell.MergeDown + 1];
#endif
XUnit height = lowerBorderPos - upperBorderPos;
height -= bordersRenderer.GetWidth(BorderType.Bottom);
XUnit x = _startX;
for (int clmIdx = 0; clmIdx < cell.Column.Index; ++clmIdx)
{
x += _table.Columns[clmIdx].Width;
}
x += LeftBorderOffset;
return new Rectangle(x, y, width, height);
}
public override void Render()
{
InitRendering();
RenderHeaderRows();
if (_startRow < _table.Rows.Count)
{
Cell cell = _table[_startRow, 0];
int cellIdx = _mergedCells.BinarySearch(_table[_startRow, 0], new CellComparer());
while (cellIdx < _mergedCells.Count)
{
cell = _mergedCells[cellIdx];
if (cell.Row.Index > _endRow)
break;
RenderCell(cell);
++cellIdx;
}
}
}
private void InitFormat(Area area, FormatInfo previousFormatInfo)
{
TableFormatInfo prevTableFormatInfo = (TableFormatInfo)previousFormatInfo;
TableRenderInfo tblRenderInfo = new TableRenderInfo();
tblRenderInfo.DocumentObject = _table;
// Equalize the two borders, that are used to determine a rounded corner's border.
// This way the innerWidth of the cell, which is got by the saved _formattedCells, is the same regardless of which corner relevant border is set.
foreach (Row row in _table.Rows)
foreach (Cell cell in row.Cells)
EqualizeRoundedCornerBorders(cell);
_renderInfo = tblRenderInfo;
if (prevTableFormatInfo != null)
{
_mergedCells = prevTableFormatInfo.MergedCells;
_formattedCells = prevTableFormatInfo.FormattedCells;
_bottomBorderMap = prevTableFormatInfo.BottomBorderMap;
_lastHeaderRow = prevTableFormatInfo.LastHeaderRow;
_connectedRowsMap = prevTableFormatInfo.ConnectedRowsMap;
_startRow = prevTableFormatInfo.EndRow + 1;
}
else
{
_mergedCells = new MergedCellList(_table);
FormatCells();
CalcLastHeaderRow();
CreateConnectedRows();
CreateBottomBorderMap();
if (_doHorizontalBreak)
{
CalcLastHeaderColumn();
CreateConnectedColumns();
}
_startRow = _lastHeaderRow + 1;
}
((TableFormatInfo)tblRenderInfo.FormatInfo).MergedCells = _mergedCells;
((TableFormatInfo)tblRenderInfo.FormatInfo).FormattedCells = _formattedCells;
((TableFormatInfo)tblRenderInfo.FormatInfo).BottomBorderMap = _bottomBorderMap;
((TableFormatInfo)tblRenderInfo.FormatInfo).ConnectedRowsMap = _connectedRowsMap;
((TableFormatInfo)tblRenderInfo.FormatInfo).LastHeaderRow = _lastHeaderRow;
}
private void FormatCells()
{
_formattedCells = new Dictionary<Cell, FormattedCell>(); //new Sorted_List(new CellComparer());
foreach (Cell cell in _mergedCells)
{
FormattedCell formattedCell = new FormattedCell(cell, _documentRenderer, _mergedCells.GetEffectiveBorders(cell),
_fieldInfos, 0, 0);
formattedCell.Format(_gfx);
_formattedCells.Add(cell, formattedCell);
}
}
/// <summary>
/// Formats (measures) the table.
/// </summary>
/// <param name="area"> The area on which to fit the table. </param>
/// <param name="previousFormatInfo"> </param>
public override void Format(Area area, FormatInfo previousFormatInfo)
{
DocumentElements elements = DocumentRelations.GetParent(_table) as DocumentElements;
if (elements != null)
{
Section section = DocumentRelations.GetParent(elements) as Section;
if (section != null)
_doHorizontalBreak = section.PageSetup.HorizontalPageBreak;
}
_renderInfo = new TableRenderInfo();
InitFormat(area, previousFormatInfo);
// Don't take any Rows higher then MaxElementHeight
XUnit topHeight = CalcStartingHeight();
XUnit probeHeight = topHeight;
XUnit offset;
if (_startRow > _lastHeaderRow + 1 &&
_startRow < _table.Rows.Count)
offset = _bottomBorderMap[_startRow] - topHeight;
else
offset = -CalcMaxTopBorderWidth(0);
int probeRow = _startRow;
XUnit currentHeight = 0;
XUnit startingHeight = 0;
bool isEmpty = false;
while (probeRow < _table.Rows.Count)
{
bool firstProbe = probeRow == _startRow;
probeRow = _connectedRowsMap[probeRow];
// Don't take any Rows higher then MaxElementHeight
probeHeight = _bottomBorderMap[probeRow + 1] - offset;
// First test whether MaxElementHeight has been set.
if (MaxElementHeight > 0 && firstProbe && probeHeight > MaxElementHeight - Tolerance)
probeHeight = MaxElementHeight - Tolerance;
//if (firstProbe && probeHeight > MaxElementHeight - Tolerance)
// probeHeight = MaxElementHeight - Tolerance;
//The height for the first new row(s) + headerrows:
if (startingHeight == 0)
{
if (probeHeight > area.Height)
{
isEmpty = true;
break;
}
startingHeight = probeHeight;
}
if (probeHeight > area.Height)
break;
else
{
_currRow = probeRow;
currentHeight = probeHeight;
++probeRow;
}
}
if (!isEmpty)
{
TableFormatInfo formatInfo = (TableFormatInfo)_renderInfo.FormatInfo;
formatInfo.StartRow = _startRow;
formatInfo._isEnding = _currRow >= _table.Rows.Count - 1;
formatInfo.EndRow = _currRow;
}
FinishLayoutInfo(area, currentHeight, startingHeight);
}
private void FinishLayoutInfo(Area area, XUnit currentHeight, XUnit startingHeight)
{
LayoutInfo layoutInfo = _renderInfo.LayoutInfo;
layoutInfo.StartingHeight = startingHeight;
//REM: Trailing height would have to be calculated in case tables had a keep with next property.
layoutInfo.TrailingHeight = 0;
if (_currRow >= 0)
{
layoutInfo.ContentArea = new Rectangle(area.X, area.Y, 0, currentHeight);
XUnit width = LeftBorderOffset;
foreach (Column clm in _table.Columns)
{
width += clm.Width;
}
layoutInfo.ContentArea.Width = width;
}
layoutInfo.MinWidth = layoutInfo.ContentArea.Width;
if (!_table.Rows._leftIndent.IsNull)
layoutInfo.Left = _table.Rows.LeftIndent.Point;
else if (_table.Rows.Alignment == RowAlignment.Left)
{
XUnit leftOffset = LeftBorderOffset;
leftOffset += _table.Columns[0].LeftPadding;
layoutInfo.Left = -leftOffset;
}
switch (_table.Rows.Alignment)
{
case RowAlignment.Left:
layoutInfo.HorizontalAlignment = ElementAlignment.Near;
break;
case RowAlignment.Right:
layoutInfo.HorizontalAlignment = ElementAlignment.Far;
break;
case RowAlignment.Center:
layoutInfo.HorizontalAlignment = ElementAlignment.Center;
break;
}
}
private XUnit LeftBorderOffset
{
get
{
if (_leftBorderOffset < 0)
{
if (_table.Rows.Count > 0 && _table.Columns.Count > 0)
{
Borders borders = _mergedCells.GetEffectiveBorders(_table[0, 0]);
BordersRenderer bordersRenderer = new BordersRenderer(borders, _gfx);
_leftBorderOffset = bordersRenderer.GetWidth(BorderType.Left);
}
else
_leftBorderOffset = 0;
}
return _leftBorderOffset;
}
}
private XUnit _leftBorderOffset = -1;
/// <summary>
/// Calcs either the height of the header rows or the height of the uppermost top border.
/// </summary>
/// <returns> </returns>
private XUnit CalcStartingHeight()
{
XUnit height = 0;
if (_lastHeaderRow >= 0)
{
height = _bottomBorderMap[_lastHeaderRow + 1];
height += CalcMaxTopBorderWidth(0);
}
else
{
if (_table.Rows.Count > _startRow)
height = CalcMaxTopBorderWidth(_startRow);
}
return height;
}
private void CalcLastHeaderColumn()
{
_lastHeaderColumn = -1;
foreach (Column clm in _table.Columns)
{
if (clm.HeadingFormat)
_lastHeaderColumn = clm.Index;
else break;
}
if (_lastHeaderColumn >= 0)
_lastHeaderRow = CalcLastConnectedColumn(_lastHeaderColumn);
// Ignore heading format if all the table is heading:
if (_lastHeaderRow == _table.Rows.Count - 1)
_lastHeaderRow = -1;
}
private void CalcLastHeaderRow()
{
_lastHeaderRow = -1;
foreach (Row row in _table.Rows)
{
if (row.HeadingFormat)
_lastHeaderRow = row.Index;
else break;
}
if (_lastHeaderRow >= 0)
_lastHeaderRow = CalcLastConnectedRow(_lastHeaderRow);
// Ignore heading format if all the table is heading:
if (_lastHeaderRow == _table.Rows.Count - 1)
_lastHeaderRow = -1;
}
private void CreateConnectedRows()
{
_connectedRowsMap = new Dictionary<int, int>(); //new Sorted_List();
foreach (Cell cell in _mergedCells)
{
if (!_connectedRowsMap.ContainsKey(cell.Row.Index))
{
int lastConnectedRow = CalcLastConnectedRow(cell.Row.Index);
_connectedRowsMap[cell.Row.Index] = lastConnectedRow;
}
}
}
private void CreateConnectedColumns()
{
_connectedColumnsMap = new Dictionary<int, int>(); //new SortedList();
foreach (Cell cell in _mergedCells)
{
if (!_connectedColumnsMap.ContainsKey(cell.Column.Index))
{
int lastConnectedColumn = CalcLastConnectedColumn(cell.Column.Index);
_connectedColumnsMap[cell.Column.Index] = lastConnectedColumn;
}
}
}
private void CreateBottomBorderMap()
{
_bottomBorderMap = new Dictionary<int, XUnit>(); //new SortedList();
_bottomBorderMap.Add(0, XUnit.FromPoint(0));
while (!_bottomBorderMap.ContainsKey(_table.Rows.Count))
{
CreateNextBottomBorderPosition();
}
}
/// <summary>
/// Calculates the top border width for the first row that is rendered or formatted.
/// </summary>
/// <param name="row"> The row index. </param>
private XUnit CalcMaxTopBorderWidth(int row)
{
XUnit maxWidth = 0;
if (_table.Rows.Count > row)
{
int cellIdx = _mergedCells.BinarySearch(_table[row, 0], new CellComparer());
Cell rowCell = _mergedCells[cellIdx];
while (cellIdx < _mergedCells.Count)
{
rowCell = _mergedCells[cellIdx];
if (rowCell.Row.Index > row)
break;
if (rowCell._borders != null && !rowCell._borders.IsNull())
{
BordersRenderer bordersRenderer = new BordersRenderer(rowCell.Borders, _gfx);
XUnit width = bordersRenderer.GetWidth(BorderType.Top);
if (width > maxWidth)
maxWidth = width;
}
++cellIdx;
}
}
return maxWidth;
}
/// <summary>
/// Creates the next bottom border position.
/// </summary>
private void CreateNextBottomBorderPosition()
{
//int lastIdx = _bottomBorderMap.Count - 1;
// SortedList version:
//int lastBorderRow = (int)bottomBorderMap.GetKey(lastIdx);
//XUnit lastPos = (XUnit)bottomBorderMap.GetByIndex(lastIdx);
int lastBorderRow = 0;
foreach (int key in _bottomBorderMap.Keys)
{
if (key > lastBorderRow)
lastBorderRow = key;
}
XUnit lastPos = _bottomBorderMap[lastBorderRow];
Cell minMergedCell = GetMinMergedCell(lastBorderRow);
FormattedCell minMergedFormattedCell = _formattedCells[minMergedCell];
XUnit maxBottomBorderPosition = lastPos + minMergedFormattedCell.InnerHeight;
maxBottomBorderPosition += CalcBottomBorderWidth(minMergedCell);
foreach (Cell cell in _mergedCells)
{
if (cell.Row.Index > minMergedCell.Row.Index + minMergedCell.MergeDown)
break;
if (cell.Row.Index + cell.MergeDown == minMergedCell.Row.Index + minMergedCell.MergeDown)
{
FormattedCell formattedCell = _formattedCells[cell];
// !!!new 18-03-09 Attempt to fix an exception. begin
// if (cell.Row.Index < _bottomBorderMap.Count)
{
// !!!new 18-03-09 Attempt to fix an exception. end
#if true
// !!!new 18-03-09 Attempt to fix an exception. begin
XUnit topBorderPos = maxBottomBorderPosition;
if (!_bottomBorderMap.TryGetValue(cell.Row.Index, out topBorderPos))
{
//GetType();
}
// !!!new 18-03-09 Attempt to fix an exception. end
#else
XUnit topBorderPos = _bottomBorderMap[cell.Row.Index];
#endif
XUnit bottomBorderPos = topBorderPos + formattedCell.InnerHeight;
bottomBorderPos += CalcBottomBorderWidth(cell);
if (bottomBorderPos > maxBottomBorderPosition)
maxBottomBorderPosition = bottomBorderPos;
// !!!new 18-03-09 Attempt to fix an exception. begin
}
// !!!new 18-03-09 Attempt to fix an exception. end
}
}
_bottomBorderMap.Add(minMergedCell.Row.Index + minMergedCell.MergeDown + 1, maxBottomBorderPosition);
}
/// <summary>
/// Calculates bottom border width of a cell.
/// </summary>
/// <param name="cell"> The cell the bottom border of the row that is probed. </param>
/// <returns> The calculated border width. </returns>
private XUnit CalcBottomBorderWidth(Cell cell)
{
Borders borders = _mergedCells.GetEffectiveBorders(cell);
if (borders != null)
{
BordersRenderer bordersRenderer = new BordersRenderer(borders, _gfx);
return bordersRenderer.GetWidth(BorderType.Bottom);
}
return 0;
}
/// <summary>
/// Gets the first cell that ends in the given row or as close as possible.
/// </summary>
/// <param name="row">The row to probe.</param>
/// <returns>The first cell with minimal vertical merge.</returns>
private Cell GetMinMergedCell(int row)
{
#if true
//!!!new 18-03-10 begin
// Also look at rows above "row", but only consider cells that end at "row" or as close as possible.
int minMerge = _table.Rows.Count;
Cell minCell = null;
foreach (Cell cell in _mergedCells)
{
if (cell.Row.Index <= row && cell.Row.Index + cell.MergeDown >= row)
{
if (cell.Row.Index == row && cell.MergeDown == 0)
{
// Perfect match: non-merged cell in the desired row.
minCell = cell;
break;
}
else if (cell.Row.Index + cell.MergeDown - row < minMerge)
{
minMerge = cell.Row.Index + cell.MergeDown - row;
minCell = cell;
}
}
else if (cell.Row.Index > row)
break;
}
//!!!new 18-03-10 end
#else
int minMerge = _table.Rows.Count;
Cell minCell = null;
foreach (Cell cell in _mergedCells)
{
if (cell.Row.Index == row)
{
if (cell.MergeDown == 0)
{
minCell = cell;
break;
}
else if (cell.MergeDown < minMerge)
{
minMerge = cell.MergeDown;
minCell = cell;
}
}
else if (cell.Row.Index > row)
break;
}
#endif
return minCell;
}
/// <summary>
/// Calculates the last row that is connected with the given row.
/// </summary>
/// <param name="row"> The row that is probed for downward connection. </param>
/// <returns> The last row that is connected with the given row. </returns>
private int CalcLastConnectedRow(int row)
{
int lastConnectedRow = row;
foreach (Cell cell in _mergedCells)
{
if (cell.Row.Index <= lastConnectedRow)
{
int downConnection = Math.Max(cell.Row.KeepWith, cell.MergeDown);
if (lastConnectedRow < cell.Row.Index + downConnection)
lastConnectedRow = cell.Row.Index + downConnection;
}
}
return lastConnectedRow;
}
/// <summary>
/// Calculates the last column that is connected with the specified column.
/// </summary>
/// <param name="column"> The column that is probed for downward connection. </param>
/// <returns> The last column that is connected with the given column. </returns>
private int CalcLastConnectedColumn(int column)
{
int lastConnectedColumn = column;
foreach (Cell cell in _mergedCells)
{
if (cell.Column.Index <= lastConnectedColumn)
{
int rightConnection = Math.Max(cell.Column.KeepWith, cell.MergeRight);
if (lastConnectedColumn < cell.Column.Index + rightConnection)
lastConnectedColumn = cell.Column.Index + rightConnection;
}
}
return lastConnectedColumn;
}
private readonly Table _table;
private MergedCellList _mergedCells;
private Dictionary<Cell, FormattedCell> _formattedCells; //SortedList formattedCells;
private Dictionary<int, XUnit> _bottomBorderMap; //SortedList bottomBorderMap;
private Dictionary<int, int> _connectedRowsMap; //SortedList connectedRowsMap;
private Dictionary<int, int> _connectedColumnsMap; //SortedList connectedColumnsMap;
private int _lastHeaderRow;
private int _lastHeaderColumn;
private int _startRow;
private int _currRow;
private int _endRow = -1;
private bool _doHorizontalBreak;
private XUnit _startX;
private XUnit _startY;
}
}

View File

@@ -0,0 +1,40 @@
#region MigraDoc - Creating Documents on the Fly
//
// Authors:
// Klaus Potzesny
//
// Copyright (c) 2001-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.com
// http://www.migradoc.com
// http://sourceforge.net/projects/pdfsharp
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#endregion
namespace MigraDoc.Rendering
{
/// <summary>
/// Formatting information for textframes.
/// </summary>
public sealed class TextFrameFormatInfo : ShapeFormatInfo
{
public FormattedTextFrame FormattedTextFrame;
}
}

View File

@@ -0,0 +1,48 @@
#region MigraDoc - Creating Documents on the Fly
//
// Authors:
// Klaus Potzesny
//
// Copyright (c) 2001-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.com
// http://www.migradoc.com
// http://sourceforge.net/projects/pdfsharp
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#endregion
namespace MigraDoc.Rendering
{
/// <summary>
/// Summary description for TextFrameRenderInfo.
/// </summary>
public sealed class TextFrameRenderInfo : ShapeRenderInfo
{
/// <summary>
/// Gets the format information in a specific derived type. For a table, for example, this will be a TableFormatInfo with information about the first and last row showing on a page.
/// </summary>
public override FormatInfo FormatInfo
{
get { return _formatInfo ?? (_formatInfo = new TextFrameFormatInfo()); }
set { _formatInfo = (TextFrameFormatInfo)value; }
}
TextFrameFormatInfo _formatInfo;
}
}

View File

@@ -0,0 +1,130 @@
#region MigraDoc - Creating Documents on the Fly
//
// Authors:
// Klaus Potzesny
//
// Copyright (c) 2001-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.com
// http://www.migradoc.com
// http://sourceforge.net/projects/pdfsharp
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#endregion
using PdfSharp.Drawing;
using MigraDoc.DocumentObjectModel.Shapes;
namespace MigraDoc.Rendering
{
/// <summary>
/// Renders textframes.
/// </summary>
public class TextFrameRenderer : ShapeRenderer
{
public TextFrameRenderer(XGraphics gfx, TextFrame textframe, FieldInfos fieldInfos)
: base(gfx, textframe, fieldInfos)
{
_textframe = textframe;
TextFrameRenderInfo renderInfo = new TextFrameRenderInfo();
renderInfo.DocumentObject = _shape;
_renderInfo = renderInfo;
}
public TextFrameRenderer(XGraphics gfx, RenderInfo renderInfo, FieldInfos fieldInfos)
: base(gfx, renderInfo, fieldInfos)
{
_textframe = (TextFrame)renderInfo.DocumentObject;
}
public override void Format(Area area, FormatInfo previousFormatInfo)
{
FormattedTextFrame formattedTextFrame = new FormattedTextFrame(_textframe, _documentRenderer, _fieldInfos);
formattedTextFrame.Format(_gfx);
((TextFrameFormatInfo)_renderInfo.FormatInfo).FormattedTextFrame = formattedTextFrame;
base.Format(area, previousFormatInfo);
}
public override LayoutInfo InitialLayoutInfo
{
get { return base.InitialLayoutInfo; }
}
public override void Render()
{
RenderFilling();
RenderContent();
RenderLine();
}
void RenderContent()
{
FormattedTextFrame formattedTextFrame = ((TextFrameFormatInfo)_renderInfo.FormatInfo).FormattedTextFrame;
RenderInfo[] renderInfos = formattedTextFrame.GetRenderInfos();
if (renderInfos == null)
return;
XGraphicsState state = Transform();
RenderByInfos(renderInfos);
ResetTransform(state);
}
XGraphicsState Transform()
{
Area frameContentArea = _renderInfo.LayoutInfo.ContentArea;
XGraphicsState state = _gfx.Save();
XUnit xPosition;
XUnit yPosition;
switch (_textframe.Orientation)
{
case TextOrientation.Downward:
case TextOrientation.Vertical:
case TextOrientation.VerticalFarEast:
xPosition = frameContentArea.X + frameContentArea.Width;
yPosition = frameContentArea.Y;
_gfx.TranslateTransform(xPosition, yPosition);
_gfx.RotateTransform(90);
break;
case TextOrientation.Upward:
state = _gfx.Save();
xPosition = frameContentArea.X;
yPosition = frameContentArea.Y + frameContentArea.Height;
_gfx.TranslateTransform(xPosition, yPosition);
_gfx.RotateTransform(-90);
break;
default:
xPosition = frameContentArea.X;
yPosition = frameContentArea.Y;
_gfx.TranslateTransform(xPosition, yPosition);
break;
}
return state;
}
void ResetTransform(XGraphicsState state)
{
if (state != null)
_gfx.Restore(state);
}
readonly TextFrame _textframe;
}
}

View File

@@ -0,0 +1,362 @@
#region MigraDoc - Creating Documents on the Fly
//
// Authors:
// Klaus Potzesny
//
// Copyright (c) 2001-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.com
// http://www.migradoc.com
// http://sourceforge.net/projects/pdfsharp
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#endregion
using System;
using System.Collections.Generic;
using MigraDoc.DocumentObjectModel;
using PdfSharp.Drawing;
namespace MigraDoc.Rendering
{
/// <summary>
/// Formats a series of document elements from top to bottom.
/// </summary>
public class TopDownFormatter
{
/// <summary>
/// Returns the max of the given Margins, if both are positive or 0, the sum otherwise.
/// </summary>
/// <param name="prevBottomMargin">The bottom margin of the previous element.</param>
/// <param name="nextTopMargin">The top margin of the next element.</param>
/// <returns></returns>
private XUnit MarginMax(XUnit prevBottomMargin, XUnit nextTopMargin)
{
if (prevBottomMargin >= 0 && nextTopMargin >= 0)
return Math.Max(prevBottomMargin, nextTopMargin);
return prevBottomMargin + nextTopMargin;
}
public TopDownFormatter(IAreaProvider areaProvider, DocumentRenderer documentRenderer, DocumentElements elements)
{
_documentRenderer = documentRenderer;
_areaProvider = areaProvider;
_elements = elements;
}
readonly IAreaProvider _areaProvider;
readonly DocumentElements _elements;
/// <summary>
/// Formats the elements on the areas provided by the area provider.
/// </summary>
/// <param name="gfx">The graphics object to render on.</param>
/// <param name="topLevel">if set to <c>true</c> formats the object is on top level.</param>
public void FormatOnAreas(XGraphics gfx, bool topLevel)
{
_gfx = gfx;
XUnit prevBottomMargin = 0;
XUnit yPos = prevBottomMargin;
RenderInfo prevRenderInfo = null;
FormatInfo prevFormatInfo = null;
List<RenderInfo> renderInfos = new List<RenderInfo>();
bool ready = _elements.Count == 0;
bool isFirstOnPage = true;
Area area = _areaProvider.GetNextArea();
XUnit maxHeight = area.Height;
if (ready)
{
_areaProvider.StoreRenderInfos(renderInfos);
return;
}
int idx = 0;
while (!ready && area != null)
{
DocumentObject docObj = _elements[idx];
Renderer renderer = Renderer.Create(gfx, _documentRenderer, docObj, _areaProvider.AreaFieldInfos);
if (renderer != null) // "Slightly hacked" for legends: see below
renderer.MaxElementHeight = maxHeight;
if (topLevel && _documentRenderer.HasPrepareDocumentProgress)
{
_documentRenderer.OnPrepareDocumentProgress(_documentRenderer.ProgressCompleted + idx + 1,
_documentRenderer.ProgressMaximum);
}
// "Slightly hacked" for legends: they are rendered as part of the chart.
// So they are skipped here.
if (renderer == null)
{
ready = idx == _elements.Count - 1;
if (ready)
_areaProvider.StoreRenderInfos(renderInfos);
++idx;
continue;
}
///////////////////////////////////////////
if (prevFormatInfo == null)
{
LayoutInfo initialLayoutInfo = renderer.InitialLayoutInfo;
XUnit distance = prevBottomMargin;
if (initialLayoutInfo.VerticalReference == VerticalReference.PreviousElement &&
initialLayoutInfo.Floating != Floating.None)
distance = MarginMax(initialLayoutInfo.MarginTop, distance);
area = area.Lower(distance);
}
renderer.Format(area, prevFormatInfo);
_areaProvider.PositionHorizontally(renderer.RenderInfo.LayoutInfo);
bool pagebreakBefore = _areaProvider.IsAreaBreakBefore(renderer.RenderInfo.LayoutInfo) && !isFirstOnPage;
pagebreakBefore = pagebreakBefore || !isFirstOnPage && IsForcedAreaBreak(idx, renderer, area);
if (!pagebreakBefore && renderer.RenderInfo.FormatInfo.IsEnding)
{
if (PreviousRendererNeedsRemoveEnding(prevRenderInfo, renderer.RenderInfo, area))
{
prevRenderInfo.RemoveEnding();
renderer = Renderer.Create(gfx, _documentRenderer, docObj, _areaProvider.AreaFieldInfos);
renderer.MaxElementHeight = maxHeight;
renderer.Format(area, prevRenderInfo.FormatInfo);
}
else if (NeedsEndingOnNextArea(idx, renderer, area, isFirstOnPage))
{
renderer.RenderInfo.RemoveEnding();
prevRenderInfo = FinishPage(renderer.RenderInfo, pagebreakBefore, ref renderInfos);
if (prevRenderInfo != null)
prevFormatInfo = prevRenderInfo.FormatInfo;
else
{
prevFormatInfo = null;
isFirstOnPage = true;
}
prevBottomMargin = 0;
area = _areaProvider.GetNextArea();
maxHeight = area.Height;
}
else
{
renderInfos.Add(renderer.RenderInfo);
isFirstOnPage = false;
_areaProvider.PositionVertically(renderer.RenderInfo.LayoutInfo);
if (renderer.RenderInfo.LayoutInfo.VerticalReference == VerticalReference.PreviousElement
&& renderer.RenderInfo.LayoutInfo.Floating != Floating.None)
{
prevBottomMargin = renderer.RenderInfo.LayoutInfo.MarginBottom;
if (renderer.RenderInfo.LayoutInfo.Floating != Floating.None)
area = area.Lower(renderer.RenderInfo.LayoutInfo.ContentArea.Height);
}
else
prevBottomMargin = 0;
prevFormatInfo = null;
prevRenderInfo = null;
++idx;
}
}
else
{
if (renderer.RenderInfo.FormatInfo.IsEmpty && isFirstOnPage)
{
area = area.Unite(new Rectangle(area.X, area.Y, area.Width, double.MaxValue));
renderer = Renderer.Create(gfx, _documentRenderer, docObj, _areaProvider.AreaFieldInfos);
renderer.MaxElementHeight = maxHeight;
renderer.Format(area, prevFormatInfo);
prevFormatInfo = null;
_areaProvider.PositionHorizontally(renderer.RenderInfo.LayoutInfo);
_areaProvider.PositionVertically(renderer.RenderInfo.LayoutInfo);
ready = idx == _elements.Count - 1;
++idx;
}
prevRenderInfo = FinishPage(renderer.RenderInfo, pagebreakBefore, ref renderInfos);
if (prevRenderInfo != null)
prevFormatInfo = prevRenderInfo.FormatInfo;
else
{
prevFormatInfo = null;
}
isFirstOnPage = true;
prevBottomMargin = 0;
if (!ready)
{
area = _areaProvider.GetNextArea();
maxHeight = area.Height;
}
}
if (idx == _elements.Count && !ready)
{
_areaProvider.StoreRenderInfos(renderInfos);
ready = true;
}
}
}
/// <summary>
/// Finishes rendering for the page.
/// </summary>
/// <param name="lastRenderInfo">The last render info.</param>
/// <param name="pagebreakBefore">set to <c>true</c> if there is a pagebreak before this page.</param>
/// <param name="renderInfos">The render infos.</param>
/// <returns>
/// The RenderInfo to set as previous RenderInfo.
/// </returns>
RenderInfo FinishPage(RenderInfo lastRenderInfo, bool pagebreakBefore, ref List<RenderInfo> renderInfos)
{
RenderInfo prevRenderInfo;
if (lastRenderInfo.FormatInfo.IsEmpty || pagebreakBefore)
{
prevRenderInfo = null;
}
else
{
prevRenderInfo = lastRenderInfo;
renderInfos.Add(lastRenderInfo);
if (lastRenderInfo.FormatInfo.IsEnding)
prevRenderInfo = null;
}
_areaProvider.StoreRenderInfos(renderInfos);
renderInfos = new List<RenderInfo>();
return prevRenderInfo;
}
/// <summary>
/// Indicates that a break between areas has to be performed before the element with the given idx.
/// </summary>
/// <param name="idx">Index of the document element.</param>
/// <param name="renderer">A formatted renderer for the document element.</param>
/// <param name="remainingArea">The remaining area.</param>
bool IsForcedAreaBreak(int idx, Renderer renderer, Area remainingArea)
{
FormatInfo formatInfo = renderer.RenderInfo.FormatInfo;
LayoutInfo layoutInfo = renderer.RenderInfo.LayoutInfo;
if (formatInfo.IsStarting && !formatInfo.StartingIsComplete)
return true;
if (layoutInfo.KeepTogether && !formatInfo.IsComplete)
return true;
if (layoutInfo.KeepTogether && layoutInfo.KeepWithNext)
{
Area area = remainingArea.Lower(layoutInfo.ContentArea.Height);
return NextElementsDontFit(idx, area, layoutInfo.MarginBottom);
}
return false;
}
/// <summary>
/// Indicates that the Ending of the element has to be removed.
/// </summary>
/// <param name="prevRenderInfo">The prev render info.</param>
/// <param name="succedingRenderInfo">The succeding render info.</param>
/// <param name="remainingArea">The remaining area.</param>
bool PreviousRendererNeedsRemoveEnding(RenderInfo prevRenderInfo, RenderInfo succedingRenderInfo, Area remainingArea)
{
if (prevRenderInfo == null)
return false;
LayoutInfo layoutInfo = succedingRenderInfo.LayoutInfo;
FormatInfo formatInfo = succedingRenderInfo.FormatInfo;
LayoutInfo prevLayoutInfo = prevRenderInfo.LayoutInfo;
if (formatInfo.IsEnding && !formatInfo.EndingIsComplete)
{
Area area = _areaProvider.ProbeNextArea();
if (area.Height > prevLayoutInfo.TrailingHeight + layoutInfo.TrailingHeight + Renderer.Tolerance)
return true;
}
return false;
}
/// <summary>
/// The maximum number of elements that can be combined via keepwithnext and keeptogether
/// </summary>
public static readonly int MaxCombineElements = 10;
bool NextElementsDontFit(int idx, Area remainingArea, XUnit previousMarginBottom)
{
XUnit elementDistance = previousMarginBottom;
Area area = remainingArea;
for (int index = idx + 1; index < _elements.Count; ++index)
{
// Never combine more than MaxCombineElements elements
if (index - idx > MaxCombineElements)
return false;
DocumentObject obj = _elements[index];
Renderer currRenderer = Renderer.Create(_gfx, _documentRenderer, obj, _areaProvider.AreaFieldInfos);
elementDistance = MarginMax(elementDistance, currRenderer.InitialLayoutInfo.MarginTop);
area = area.Lower(elementDistance);
if (area.Height <= 0)
return true;
currRenderer.Format(area, null);
FormatInfo currFormatInfo = currRenderer.RenderInfo.FormatInfo;
LayoutInfo currLayoutInfo = currRenderer.RenderInfo.LayoutInfo;
if (currLayoutInfo.VerticalReference != VerticalReference.PreviousElement)
return false;
if (!currFormatInfo.StartingIsComplete)
return true;
if (currLayoutInfo.KeepTogether && !currFormatInfo.IsComplete)
return true;
if (!(currLayoutInfo.KeepTogether && currLayoutInfo.KeepWithNext))
return false;
area = area.Lower(currLayoutInfo.ContentArea.Height);
if (area.Height <= 0)
return true;
elementDistance = currLayoutInfo.MarginBottom;
}
return false;
}
bool NeedsEndingOnNextArea(int idx, Renderer renderer, Area remainingArea, bool isFirstOnPage)
{
LayoutInfo layoutInfo = renderer.RenderInfo.LayoutInfo;
if (isFirstOnPage && layoutInfo.KeepTogether)
return false;
FormatInfo formatInfo = renderer.RenderInfo.FormatInfo;
if (!formatInfo.EndingIsComplete)
return false;
if (layoutInfo.KeepWithNext)
{
remainingArea = remainingArea.Lower(layoutInfo.ContentArea.Height);
return NextElementsDontFit(idx, remainingArea, layoutInfo.MarginBottom);
}
return false;
}
readonly DocumentRenderer _documentRenderer;
XGraphics _gfx;
}
}

View File

@@ -0,0 +1,44 @@
#region MigraDoc - Creating Documents on the Fly
//
// Authors:
// Klaus Potzesny
//
// Copyright (c) 2001-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.com
// http://www.migradoc.com
// http://sourceforge.net/projects/pdfsharp
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#endregion
namespace MigraDoc.Rendering
{
/// <summary>
/// Alignment of layout elements.
/// </summary>
public enum ElementAlignment
{
Near = 0, // Default
Center,
Far,
Inside,
Outside
}
}

View File

@@ -0,0 +1,46 @@
#region MigraDoc - Creating Documents on the Fly
//
// Authors:
// Klaus Potzesny
//
// Copyright (c) 2001-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.com
// http://www.migradoc.com
// http://sourceforge.net/projects/pdfsharp
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#endregion
namespace MigraDoc.Rendering
{
/// <summary>
/// Floating behavior of layout elements.
/// </summary>
public enum Floating
{
TopBottom = 0, // Default
None, // The element is ignored.
// Served for future extensions:
Left,
Right,
BothSides,
}
}

View File

@@ -0,0 +1,42 @@
#region MigraDoc - Creating Documents on the Fly
//
// Authors:
// Klaus Potzesny
//
// Copyright (c) 2001-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.com
// http://www.migradoc.com
// http://sourceforge.net/projects/pdfsharp
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#endregion
namespace MigraDoc.Rendering
{
/// <summary>
/// Horizontal reference point of alignment.
/// </summary>
public enum HorizontalReference
{
AreaBoundary = 0, // Default
PageMargin,
Page
}
}

View File

@@ -0,0 +1,41 @@
#region MigraDoc - Creating Documents on the Fly
//
// Authors:
// Klaus Potzesny
//
// Copyright (c) 2001-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.com
// http://www.migradoc.com
// http://sourceforge.net/projects/pdfsharp
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#endregion
namespace MigraDoc.Rendering
{
public enum ImageFailure
{
None = 0,
FileNotFound,
InvalidType,
NotRead,
EmptySize
}
}

View File

@@ -0,0 +1,81 @@
#region MigraDoc - Creating Documents on the Fly
//
// Authors:
// Klaus Potzesny
//
// Copyright (c) 2001-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.com
// http://www.migradoc.com
// http://sourceforge.net/projects/pdfsharp
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#endregion
using System;
namespace MigraDoc.Rendering
{
/// <summary>
/// Determines the parts of a page to be rendered.
/// </summary>
[Flags]
public enum PageRenderOptions
{
/// <summary>
/// Renders nothing (creates an empty page).
/// </summary>
None = 0,
/// <summary>
/// Renders Headers.
/// </summary>
RenderHeader = 1,
/// <summary>
/// Renders Footers.
/// </summary>
RenderFooter = 2,
/// <summary>
/// Renders Content.
/// </summary>
RenderContent = 4,
/// <summary>
/// Renders PDF background pages.
/// </summary>
RenderPdfBackground = 8,
/// <summary>
/// Renders PDF content pages.
/// </summary>
RenderPdfContent = 16,
/// <summary>
/// Renders all.
/// </summary>
All = RenderHeader | RenderFooter | RenderContent | RenderPdfBackground | RenderPdfContent,
/// <summary>
/// Creates not even an empty page.
/// </summary>
RemovePage = 32
}
}

View File

@@ -0,0 +1,40 @@
#region MigraDoc - Creating Documents on the Fly
//
// Authors:
// Klaus Potzesny
//
// Copyright (c) 2001-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.com
// http://www.migradoc.com
// http://sourceforge.net/projects/pdfsharp
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#endregion
namespace MigraDoc.Rendering
{
public enum VerticalReference
{
PreviousElement = 0, // Default
AreaBoundary,
PageMargin,
Page
}
}