diff --git a/PdfSharpCore.Test/IO/LargePDFReadWrite.cs b/PdfSharpCore.Test/IO/LargePDFReadWrite.cs index a83d8c43..db91d056 100644 --- a/PdfSharpCore.Test/IO/LargePDFReadWrite.cs +++ b/PdfSharpCore.Test/IO/LargePDFReadWrite.cs @@ -53,7 +53,7 @@ private void AddAPage(PdfDocument document, XFont font) var height = page.Height.Value - 50 - y; var rect = new XRect(40, 50, width, height); renderer.DrawRectangle(XBrushes.SeaShell, rect); - tf.DrawString(TestData.LoremIpsumText, font, XBrushes.Black, rect, XStringFormats.TopLeft); + tf.DrawString(TestData.LoremIpsumText, font, XBrushes.Black, rect); } } } \ No newline at end of file diff --git a/PdfSharpCore/Drawing.Layout/XTextFormatter.cs b/PdfSharpCore/Drawing.Layout/XTextFormatter.cs index b4e1e5bf..c3367059 100644 --- a/PdfSharpCore/Drawing.Layout/XTextFormatter.cs +++ b/PdfSharpCore/Drawing.Layout/XTextFormatter.cs @@ -138,20 +138,25 @@ public void SetAlignment(TextFormatAlignment alignments) /// The font. /// The text brush. /// The layout rectangle. + /// The line height. public void DrawString(string text, XFont font, XBrush brush, XRect layoutRectangle, XUnit? lineHeight = null) { - DrawString(text, font, brush, layoutRectangle, XStringFormats.TopLeft, lineHeight); + DrawString(text, font, brush, layoutRectangle, new TextFormatAlignment() + { + Horizontal = XParagraphAlignment.Justify, Vertical = XVerticalAlignment.Top + }, lineHeight); } /// - /// Draws the text. + /// Get the layout rectangle required. /// /// The text to be drawn. /// The font. /// The text brush. /// The layout rectangle. - /// The format. Must be XStringFormat.TopLeft - public void DrawString(string text, XFont font, XBrush brush, XRect layoutRectangle, XStringFormat format, XUnit? lineHeight = null) + /// The height of each line + public XRect GetLayout(string text, XFont font, XBrush brush, XRect layoutRectangle, + XUnit? lineHeight = null) { if (text == null) throw new ArgumentNullException("text"); @@ -159,8 +164,6 @@ public void DrawString(string text, XFont font, XBrush brush, XRect layoutRectan throw new ArgumentNullException("font"); if (brush == null) throw new ArgumentNullException("brush"); - if (format.Alignment != XStringAlignment.Near || format.LineAlignment != XLineAlignment.Near) - throw new ArgumentException("Only TopLeft alignment is currently implemented."); Text = text; Font = font; @@ -169,36 +172,84 @@ public void DrawString(string text, XFont font, XBrush brush, XRect layoutRectan _lineHeight = lineHeight?.Point ?? _lineSpace; if (text.Length == 0) - return; + return new XRect(layoutRectangle.Location.X, layoutRectangle.Location.Y, 0, 0); CreateBlocks(); CreateLayout(); + return _layoutRectangle; + } + + /// + /// Draws the text. + /// + /// The text to be drawn. + /// The font. + /// The text brush. + /// The layout rectangle. + /// The alignments. + /// The height of each line. + public void DrawString(string text, XFont font, XBrush brush, XRect layoutRectangle, TextFormatAlignment alignments, + XUnit? lineHeight = null) + { + if (alignments == null) + throw new ArgumentNullException(nameof(alignments)); + + if (text.Length == 0) + return; + + GetLayout(text, font, brush, layoutRectangle, lineHeight); + + SetAlignment(alignments); + double dx = layoutRectangle.Location.X; - double dy = layoutRectangle.Location.Y + _cyAscent; - + double dy = layoutRectangle.Location.Y; + + var lines = GetLines(_blocks).ToArray(); + if (VerticalAlignment == XVerticalAlignment.Middle) { - dy += layoutRectangle.Height / 2 - _layoutRectangle.Height / 2 - _cyDescent; + dy += (layoutRectangle.Height - _layoutRectangle.Height) / 2; } else if (VerticalAlignment == XVerticalAlignment.Bottom) { - dy = layoutRectangle.Location.Y + layoutRectangle.Height - _layoutRectangle.Height + _lineHeight - _cyDescent; + dy = layoutRectangle.Location.Y + layoutRectangle.Height - _layoutRectangle.Height + _lineHeight - + _cyDescent; } - + int count = _blocks.Count; - for (int idx = 0; idx < count; idx++) + foreach (var line in lines) { - Block block = _blocks[idx]; - if (block.Stop) - break; - if (block.Type == BlockType.LineBreak) - continue; - _gfx.DrawString(block.Text, font, brush, dx + block.Location.X, dy + block.Location.Y); + var lineBlocks = line as Block[] ?? line.ToArray(); + if (Alignment == XParagraphAlignment.Justify) + { + var locationX = dx; + var gapSize = (layoutRectangle.Width - lineBlocks.Select(l => l.Width).Sum())/ (lineBlocks.Count() - 1); + foreach (var block in lineBlocks) + { + _gfx.DrawString(block.Text.Trim(), font, brush, locationX, dy + lineBlocks.First().Location.Y, XStringFormats.TopLeft); + locationX += block.Width + gapSize; + } + } + else + { + var lineText = string.Join(" ", lineBlocks.Select(l => l.Text)); + var locationX = dx; + if (Alignment == XParagraphAlignment.Center) + locationX = dx + layoutRectangle.Width / 2; + if (Alignment == XParagraphAlignment.Right) + locationX += layoutRectangle.Width; + _gfx.DrawString(lineText, font, brush, locationX, dy + lineBlocks.First().Location.Y, GetXStringFormat()); + } } } + private static IEnumerable> GetLines(List blocks) + { + return blocks.GroupBy(b => b.Location.Y); + } + void CreateBlocks() { _blocks.Clear(); @@ -378,6 +429,22 @@ void HorizontalAlignLine(int firstIndex, int lastIndex, double layoutWidth) // - underline and strike-out variation // - super- and sub-script // - ... + + private XStringFormat GetXStringFormat() + { + switch (Alignment) + { + case XParagraphAlignment.Center: + return XStringFormats.TopCenter; + case XParagraphAlignment.Right: + return XStringFormats.TopRight; + case XParagraphAlignment.Default: + case XParagraphAlignment.Justify: + case XParagraphAlignment.Left: + default: + return XStringFormats.TopLeft; + } + } } public class TextFormatAlignment diff --git a/PdfSharpCore/PdfSharpCore.csproj b/PdfSharpCore/PdfSharpCore.csproj index f203595a..7fc4d462 100644 --- a/PdfSharpCore/PdfSharpCore.csproj +++ b/PdfSharpCore/PdfSharpCore.csproj @@ -18,6 +18,7 @@ PdfSharpCore is a partial port of PdfSharp.Xamarin for .NET Core Additionally Mi PdfSharp for .NET Core true true + 1.0.1 diff --git a/SampleApp/Program.cs b/SampleApp/Program.cs index 1f46c514..2a049427 100644 --- a/SampleApp/Program.cs +++ b/SampleApp/Program.cs @@ -1,4 +1,8 @@ - +using PdfSharpCore.Drawing; +using PdfSharpCore.Drawing.Layout; +using PdfSharpCore.Drawing.Layout.enums; +using PdfSharpCore.Pdf; + namespace SampleApp { @@ -33,19 +37,62 @@ public static void Main(string[] args) const string outName = "test1.pdf"; - PdfSharpCore.Pdf.PdfDocument? document = new PdfSharpCore.Pdf.PdfDocument(); + PdfDocument? document = new PdfDocument(); - PdfSharpCore.Pdf.PdfPage? pageNewRenderer = document.AddPage(); + PdfPage? pageNewRenderer = document.AddPage(); - PdfSharpCore.Drawing.XGraphics? renderer = PdfSharpCore.Drawing.XGraphics.FromPdfPage(pageNewRenderer); + XGraphics? renderer = XGraphics.FromPdfPage(pageNewRenderer); renderer.DrawString( - "Testy Test Test" - , new PdfSharpCore.Drawing.XFont("Arial", 12) - , PdfSharpCore.Drawing.XBrushes.Black - , new PdfSharpCore.Drawing.XPoint(12, 12) + "Testy Test Test" + , new XFont("Arial", 12) + , XBrushes.Black + , new XPoint(12, 12) + ); + + XTextFormatter? formatter = new XTextFormatter(renderer); + + var font = new XFont("Arial", 12); + var brush = XBrushes.Black; + + formatter.AllowVerticalOverflow = true; + var originalLayout = new XRect(0, 30, 120, 120); + var text = "More and more text boxes to show alignment capabilities"; // " with addipional gline"; + var anotherText = + "Text to determine the size of the box I would like to place the text I'm goint to test"; + var rect = formatter.GetLayout( + anotherText, + font, + brush, + originalLayout); + rect.Location = new XPoint(50, 50); + formatter.AllowVerticalOverflow = false; + + // Prepare brush to draw the box that demostrates the text fits and aligns correctly + var translucentBrush = new XSolidBrush(XColor.FromArgb(20, 0, 0, 0)); + + // Draw the string with default alignments + formatter.DrawString( + text, + font, + brush, + rect ); + // For checking purposes + renderer.DrawRectangle(translucentBrush, rect); + rect.Location = new XPoint(300, 50); + + // Draw the string with custom alignments + formatter.DrawString(text, font, brush, rect, new TextFormatAlignment() + { + Horizontal = XParagraphAlignment.Center, + Vertical = XVerticalAlignment.Middle + }); + + // For checking purposes + renderer.DrawRectangle(translucentBrush, rect); + SaveDocument(document, outName); System.Console.WriteLine("Done!");