Test
This commit is contained in:
192
PrintPDF/MigraDoc.Rendering/Rendering/Area.cs
Normal file
192
PrintPDF/MigraDoc.Rendering/Rendering/Area.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
305
PrintPDF/MigraDoc.Rendering/Rendering/BordersRenderer.cs
Normal file
305
PrintPDF/MigraDoc.Rendering/Rendering/BordersRenderer.cs
Normal 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;
|
||||
}
|
||||
}
|
48
PrintPDF/MigraDoc.Rendering/Rendering/ChartFormatInfo.cs
Normal file
48
PrintPDF/MigraDoc.Rendering/Rendering/ChartFormatInfo.cs
Normal 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;
|
||||
}
|
||||
}
|
48
PrintPDF/MigraDoc.Rendering/Rendering/ChartRenderInfo.cs
Normal file
48
PrintPDF/MigraDoc.Rendering/Rendering/ChartRenderInfo.cs
Normal 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;
|
||||
}
|
||||
}
|
368
PrintPDF/MigraDoc.Rendering/Rendering/ChartRenderer.cs
Normal file
368
PrintPDF/MigraDoc.Rendering/Rendering/ChartRenderer.cs
Normal 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;
|
||||
}
|
||||
}
|
51
PrintPDF/MigraDoc.Rendering/Rendering/ColorHelper.cs
Normal file
51
PrintPDF/MigraDoc.Rendering/Rendering/ColorHelper.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
405
PrintPDF/MigraDoc.Rendering/Rendering/DocumentRenderer.cs
Normal file
405
PrintPDF/MigraDoc.Rendering/Rendering/DocumentRenderer.cs
Normal 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;
|
||||
}
|
||||
}
|
98
PrintPDF/MigraDoc.Rendering/Rendering/FieldInfos.cs
Normal file
98
PrintPDF/MigraDoc.Rendering/Rendering/FieldInfos.cs
Normal 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;
|
||||
}
|
||||
}
|
79
PrintPDF/MigraDoc.Rendering/Rendering/FillFormatRenderer.cs
Normal file
79
PrintPDF/MigraDoc.Rendering/Rendering/FillFormatRenderer.cs
Normal 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;
|
||||
}
|
||||
}
|
141
PrintPDF/MigraDoc.Rendering/Rendering/FontHandler.cs
Normal file
141
PrintPDF/MigraDoc.Rendering/Rendering/FontHandler.cs
Normal 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
|
||||
}
|
||||
}
|
83
PrintPDF/MigraDoc.Rendering/Rendering/FormatInfo.cs
Normal file
83
PrintPDF/MigraDoc.Rendering/Rendering/FormatInfo.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
201
PrintPDF/MigraDoc.Rendering/Rendering/FormattedCell.cs
Normal file
201
PrintPDF/MigraDoc.Rendering/Rendering/FormattedCell.cs
Normal 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;
|
||||
}
|
||||
}
|
725
PrintPDF/MigraDoc.Rendering/Rendering/FormattedDocument.cs
Normal file
725
PrintPDF/MigraDoc.Rendering/Rendering/FormattedDocument.cs
Normal 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;
|
||||
}
|
||||
}
|
128
PrintPDF/MigraDoc.Rendering/Rendering/FormattedHeaderFooter.cs
Normal file
128
PrintPDF/MigraDoc.Rendering/Rendering/FormattedHeaderFooter.cs
Normal 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;
|
||||
}
|
||||
}
|
171
PrintPDF/MigraDoc.Rendering/Rendering/FormattedTextArea.cs
Normal file
171
PrintPDF/MigraDoc.Rendering/Rendering/FormattedTextArea.cs
Normal 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;
|
||||
}
|
||||
}
|
180
PrintPDF/MigraDoc.Rendering/Rendering/FormattedTextFrame.cs
Normal file
180
PrintPDF/MigraDoc.Rendering/Rendering/FormattedTextFrame.cs
Normal 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;
|
||||
}
|
||||
}
|
78
PrintPDF/MigraDoc.Rendering/Rendering/IAreaProvider.cs
Normal file
78
PrintPDF/MigraDoc.Rendering/Rendering/IAreaProvider.cs
Normal 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);
|
||||
}
|
||||
}
|
50
PrintPDF/MigraDoc.Rendering/Rendering/ImageFormatInfo.cs
Normal file
50
PrintPDF/MigraDoc.Rendering/Rendering/ImageFormatInfo.cs
Normal 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;
|
||||
}
|
||||
}
|
48
PrintPDF/MigraDoc.Rendering/Rendering/ImageRenderInfo.cs
Normal file
48
PrintPDF/MigraDoc.Rendering/Rendering/ImageRenderInfo.cs
Normal 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;
|
||||
}
|
||||
}
|
367
PrintPDF/MigraDoc.Rendering/Rendering/ImageRenderer.cs
Normal file
367
PrintPDF/MigraDoc.Rendering/Rendering/ImageRenderer.cs
Normal 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;
|
||||
}
|
||||
}
|
229
PrintPDF/MigraDoc.Rendering/Rendering/LayoutInfo.cs
Normal file
229
PrintPDF/MigraDoc.Rendering/Rendering/LayoutInfo.cs
Normal 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;
|
||||
}
|
||||
}
|
122
PrintPDF/MigraDoc.Rendering/Rendering/LineFormatRenderer.cs
Normal file
122
PrintPDF/MigraDoc.Rendering/Rendering/LineFormatRenderer.cs
Normal 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;
|
||||
}
|
||||
}
|
125
PrintPDF/MigraDoc.Rendering/Rendering/NumberFormatter.cs
Normal file
125
PrintPDF/MigraDoc.Rendering/Rendering/NumberFormatter.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
68
PrintPDF/MigraDoc.Rendering/Rendering/PageBreakFormatInfo.cs
Normal file
68
PrintPDF/MigraDoc.Rendering/Rendering/PageBreakFormatInfo.cs
Normal 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; }
|
||||
}
|
||||
}
|
||||
}
|
63
PrintPDF/MigraDoc.Rendering/Rendering/PageBreakRenderInfo.cs
Normal file
63
PrintPDF/MigraDoc.Rendering/Rendering/PageBreakRenderInfo.cs
Normal 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;
|
||||
}
|
||||
}
|
92
PrintPDF/MigraDoc.Rendering/Rendering/PageBreakRenderer.cs
Normal file
92
PrintPDF/MigraDoc.Rendering/Rendering/PageBreakRenderer.cs
Normal 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;
|
||||
}
|
||||
}
|
79
PrintPDF/MigraDoc.Rendering/Rendering/PageInfo.cs
Normal file
79
PrintPDF/MigraDoc.Rendering/Rendering/PageInfo.cs
Normal 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;
|
||||
}
|
||||
}
|
187
PrintPDF/MigraDoc.Rendering/Rendering/ParagraphFormatInfo.cs
Normal file
187
PrintPDF/MigraDoc.Rendering/Rendering/ParagraphFormatInfo.cs
Normal 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>();
|
||||
}
|
||||
}
|
286
PrintPDF/MigraDoc.Rendering/Rendering/ParagraphIterator.cs
Normal file
286
PrintPDF/MigraDoc.Rendering/Rendering/ParagraphIterator.cs
Normal 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;
|
||||
}
|
||||
}
|
71
PrintPDF/MigraDoc.Rendering/Rendering/ParagraphRenderInfo.cs
Normal file
71
PrintPDF/MigraDoc.Rendering/Rendering/ParagraphRenderInfo.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
2545
PrintPDF/MigraDoc.Rendering/Rendering/ParagraphRenderer.cs
Normal file
2545
PrintPDF/MigraDoc.Rendering/Rendering/ParagraphRenderer.cs
Normal file
File diff suppressed because it is too large
Load Diff
319
PrintPDF/MigraDoc.Rendering/Rendering/PdfDocumentRenderer.cs
Normal file
319
PrintPDF/MigraDoc.Rendering/Rendering/PdfDocumentRenderer.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
207
PrintPDF/MigraDoc.Rendering/Rendering/PdfPrinter.cs
Normal file
207
PrintPDF/MigraDoc.Rendering/Rendering/PdfPrinter.cs
Normal 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
|
81
PrintPDF/MigraDoc.Rendering/Rendering/RenderInfo.cs
Normal file
81
PrintPDF/MigraDoc.Rendering/Rendering/RenderInfo.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
211
PrintPDF/MigraDoc.Rendering/Rendering/Renderer.cs
Normal file
211
PrintPDF/MigraDoc.Rendering/Rendering/Renderer.cs
Normal 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;
|
||||
}
|
||||
}
|
120
PrintPDF/MigraDoc.Rendering/Rendering/ShadingRenderer.cs
Normal file
120
PrintPDF/MigraDoc.Rendering/Rendering/ShadingRenderer.cs
Normal 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;
|
||||
}
|
||||
}
|
77
PrintPDF/MigraDoc.Rendering/Rendering/ShapeFormatInfo.cs
Normal file
77
PrintPDF/MigraDoc.Rendering/Rendering/ShapeFormatInfo.cs
Normal 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;
|
||||
}
|
||||
}
|
54
PrintPDF/MigraDoc.Rendering/Rendering/ShapeRenderInfo.cs
Normal file
54
PrintPDF/MigraDoc.Rendering/Rendering/ShapeRenderInfo.cs
Normal 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;
|
||||
}
|
||||
}
|
234
PrintPDF/MigraDoc.Rendering/Rendering/ShapeRenderer.cs
Normal file
234
PrintPDF/MigraDoc.Rendering/Rendering/ShapeRenderer.cs
Normal 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;
|
||||
}
|
||||
}
|
98
PrintPDF/MigraDoc.Rendering/Rendering/TableFormatInfo.cs
Normal file
98
PrintPDF/MigraDoc.Rendering/Rendering/TableFormatInfo.cs
Normal 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;
|
||||
}
|
||||
}
|
64
PrintPDF/MigraDoc.Rendering/Rendering/TableRenderInfo.cs
Normal file
64
PrintPDF/MigraDoc.Rendering/Rendering/TableRenderInfo.cs
Normal 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;
|
||||
}
|
||||
}
|
821
PrintPDF/MigraDoc.Rendering/Rendering/TableRenderer.cs
Normal file
821
PrintPDF/MigraDoc.Rendering/Rendering/TableRenderer.cs
Normal 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;
|
||||
}
|
||||
}
|
40
PrintPDF/MigraDoc.Rendering/Rendering/TextFrameFormatInfo.cs
Normal file
40
PrintPDF/MigraDoc.Rendering/Rendering/TextFrameFormatInfo.cs
Normal 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;
|
||||
}
|
||||
}
|
48
PrintPDF/MigraDoc.Rendering/Rendering/TextFrameRenderInfo.cs
Normal file
48
PrintPDF/MigraDoc.Rendering/Rendering/TextFrameRenderInfo.cs
Normal 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;
|
||||
}
|
||||
}
|
130
PrintPDF/MigraDoc.Rendering/Rendering/TextFrameRenderer.cs
Normal file
130
PrintPDF/MigraDoc.Rendering/Rendering/TextFrameRenderer.cs
Normal 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;
|
||||
}
|
||||
}
|
362
PrintPDF/MigraDoc.Rendering/Rendering/TopDownFormatter.cs
Normal file
362
PrintPDF/MigraDoc.Rendering/Rendering/TopDownFormatter.cs
Normal 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;
|
||||
}
|
||||
}
|
@@ -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
|
||||
}
|
||||
}
|
46
PrintPDF/MigraDoc.Rendering/Rendering/enums/Floating.cs
Normal file
46
PrintPDF/MigraDoc.Rendering/Rendering/enums/Floating.cs
Normal 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,
|
||||
}
|
||||
}
|
@@ -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
|
||||
}
|
||||
}
|
41
PrintPDF/MigraDoc.Rendering/Rendering/enums/ImageFailure.cs
Normal file
41
PrintPDF/MigraDoc.Rendering/Rendering/enums/ImageFailure.cs
Normal 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
|
||||
}
|
||||
}
|
@@ -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
|
||||
}
|
||||
}
|
@@ -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
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user