ASCU_ALL/MigraDoc.Rendering/Rendering/ShapeRenderer.cs

235 lines
9.0 KiB
C#
Raw Normal View History

2020-09-04 12:49:15 +05:00
#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;
}
}