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