From c7008ad9401020b34e9d77fbd2e7fa37ea9b7971 Mon Sep 17 00:00:00 2001 From: MarcinZiabek Date: Wed, 29 Dec 2021 22:51:01 +0100 Subject: [PATCH] Improved wrapping support --- QuestPDF.Examples/FrameExample.cs | 3 +- QuestPDF.Examples/TableExamples.cs | 4 +-- QuestPDF/Elements/Table/Table.cs | 47 ++++++++++++++++++---------- QuestPDF/Elements/Table/TableCell.cs | 2 ++ 4 files changed, 37 insertions(+), 19 deletions(-) diff --git a/QuestPDF.Examples/FrameExample.cs b/QuestPDF.Examples/FrameExample.cs index ae058ce..c77bfed 100644 --- a/QuestPDF.Examples/FrameExample.cs +++ b/QuestPDF.Examples/FrameExample.cs @@ -13,7 +13,8 @@ namespace QuestPDF.Examples return container .Border(1) .Background(dark ? Colors.Grey.Lighten2 : Colors.White) - .Padding(5); + .Padding(5) + .EnsureSpace(10); } public static void LabelCell(this IContainer container, string text) => container.Cell(true).Text(text, TextStyle.Default.SemiBold()); diff --git a/QuestPDF.Examples/TableExamples.cs b/QuestPDF.Examples/TableExamples.cs index f5498c1..3f62bde 100644 --- a/QuestPDF.Examples/TableExamples.cs +++ b/QuestPDF.Examples/TableExamples.cs @@ -103,7 +103,7 @@ namespace QuestPDF.Examples .ProducePdf() .PageSize(PageSizes.A4) .ShowResults() - .Render(container => GeneratePerformanceStructure(container, 2)); + .Render(container => GeneratePerformanceStructure(container, 10)); } [Test] @@ -117,7 +117,7 @@ namespace QuestPDF.Examples .EnableCaching() .EnableDebugging(false) .ShowResults() - .Render(container => GeneratePerformanceStructure(container, 100)); + .Render(container => GeneratePerformanceStructure(container, 250)); } public static void GeneratePerformanceStructure(IContainer container, int repeats) diff --git a/QuestPDF/Elements/Table/Table.cs b/QuestPDF/Elements/Table/Table.cs index 0a86b35..71ac21d 100644 --- a/QuestPDF/Elements/Table/Table.cs +++ b/QuestPDF/Elements/Table/Table.cs @@ -67,6 +67,7 @@ namespace QuestPDF.Elements.Table .ToArray(); } + Children.ForEach(x => x.IsRendered = false); CurrentRow = 1; } @@ -89,6 +90,11 @@ namespace QuestPDF.Elements.Table foreach (var command in layout.CellRenderingCommands) { + var measurementResult = command.Cell.Measure(command.Size); + + if (measurementResult.Type == SpacePlanType.FullRender) + command.Cell.IsRendered = true; + Canvas.Translate(command.Offset); command.Cell.Draw(command.Size); Canvas.Translate(command.Offset.Reverse()); @@ -123,11 +129,15 @@ namespace QuestPDF.Elements.Table // update row heights var rowBottomOffsets = new DynamicDictionary(); var childrenToTry = Enumerable.Range(CurrentRow, RowsCount - CurrentRow + 1).SelectMany(x => OrderedChildren[x]); - + + var maxRenderingRow = RowsCount; var currentRow = CurrentRow; foreach (var child in childrenToTry) { + if (child.Row > maxRenderingRow) + break; + if (child.Row > currentRow) { rowBottomOffsets[currentRow] = Math.Max(rowBottomOffsets[currentRow], rowBottomOffsets[currentRow - 1]); @@ -139,9 +149,21 @@ namespace QuestPDF.Elements.Table } var topOffset = rowBottomOffsets[child.Row - 1]; + var availableHeight = availableSpace.Height - topOffset; - var height = GetCellSize(child).Height; - var cellBottomOffset = height + topOffset; + var cellSize = GetCellSize(child, availableHeight); + + if (cellSize.Type == SpacePlanType.PartialRender) + { + maxRenderingRow = Math.Min(maxRenderingRow, child.Row + child.RowSpan - 1); + } + + if (cellSize.Type == SpacePlanType.Wrap) + { + maxRenderingRow = Math.Min(maxRenderingRow, child.Row - 1); + } + + var cellBottomOffset = cellSize.Height + topOffset; var targetRowId = child.Row + child.RowSpan - 1; // -1 because rowSpan starts at 1 rowBottomOffsets[targetRowId] = Math.Max(rowBottomOffsets[targetRowId], cellBottomOffset); @@ -155,13 +177,11 @@ namespace QuestPDF.Elements.Table .ForEach(x => rowHeights[x] = rowBottomOffsets[x] - rowBottomOffsets[x-1]); // find rows count to render in this pass - var maxRowToDisplay = rowBottomOffsets.Items.Where(x => x.Value <= availableSpace.Height + Size.Epsilon).Max(x => x.Key); - - var totalHeight = rowHeights.Items.Where(x => x.Key <= maxRowToDisplay).Sum(x => x.Value); + var totalHeight = rowHeights.Items.Where(x => x.Key <= maxRenderingRow).Sum(x => x.Value); var totalWidth = Columns.Sum(x => x.Width); var childrenToDraw = Enumerable - .Range(CurrentRow, maxRowToDisplay - CurrentRow + 1) + .Range(CurrentRow, maxRenderingRow - CurrentRow + 1) .SelectMany(x => OrderedChildren[x]); foreach (var cell in childrenToDraw) @@ -184,7 +204,7 @@ namespace QuestPDF.Elements.Table { Size = new Size(totalWidth, totalHeight), CellRenderingCommands = cellRenderingCommands, - MaxRowRendered = maxRowToDisplay + MaxRowRendered = maxRenderingRow }; float GetCellWidth(TableCell cell) @@ -192,17 +212,12 @@ namespace QuestPDF.Elements.Table return cellOffsets[cell.Column + cell.ColumnSpan - 1] - cellOffsets[cell.Column - 1]; } - Size GetCellSize(TableCell cell) + SpacePlan GetCellSize(TableCell cell, float availableHeight) { var width = GetCellWidth(cell); - var cellSize = new Size(width, Size.Max.Height); + var cellSize = new Size(width, availableHeight); - var measurement = cell.Measure(cellSize); - - if (measurement.Type == SpacePlanType.Wrap) - return new Size(width, Size.Infinity); - - return measurement; + return cell.Measure(cellSize); } } } diff --git a/QuestPDF/Elements/Table/TableCell.cs b/QuestPDF/Elements/Table/TableCell.cs index 2b8cc5c..7512116 100644 --- a/QuestPDF/Elements/Table/TableCell.cs +++ b/QuestPDF/Elements/Table/TableCell.cs @@ -7,5 +7,7 @@ namespace QuestPDF.Elements.Table public int Column { get; set; } = 1; public int ColumnSpan { get; set; } = 1; + + public bool IsRendered { get; set; } } } \ No newline at end of file