Skip to content

Commit 17dc24d

Browse files
committed
Improve large tables processing. Add new tests.
Check whether LayoutResult.NOTHING was caused because iText cannot place any row on layout area or iText has already placed some rows. Process remain width correctly. DEVSIX-1603
1 parent a779c2e commit 17dc24d

File tree

5 files changed

+132
-9
lines changed

5 files changed

+132
-9
lines changed

layout/src/main/java/com/itextpdf/layout/renderer/TableRenderer.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,7 @@ public LayoutResult layout(LayoutContext layoutContext) {
221221
// The last flushed row. Empty list if the table hasn't been set incomplete
222222
List<Border> lastFlushedRowBottomBorder = tableModel.getLastRowBottomBorder();
223223
boolean isAndWasComplete = tableModel.isComplete() && 0 == lastFlushedRowBottomBorder.size();
224+
boolean isFirstOnThePage = 0 == rowRange.getStartRow() || area.isEmptyArea();
224225

225226
if (!isFooterRenderer() && !isHeaderRenderer()) {
226227
if (isOriginalNonSplitRenderer) {
@@ -229,7 +230,7 @@ public LayoutResult layout(LayoutContext layoutContext) {
229230
}
230231
}
231232
bordersHandler.setRowRange(rowRange.getStartRow(), rowRange.getFinishRow());
232-
initializeHeaderAndFooter(0 == rowRange.getStartRow() || area.isEmptyArea());
233+
initializeHeaderAndFooter(isFirstOnThePage);
233234

234235
// update
235236
bordersHandler.updateBordersOnNewPage(isOriginalNonSplitRenderer, isFooterRenderer() || isHeaderRenderer(), this, headerRenderer, footerRenderer);
@@ -720,7 +721,7 @@ public LayoutResult layout(LayoutContext layoutContext) {
720721
} else {
721722
bordersHandler.applyTopTableBorder(occupiedArea.getBBox(), layoutBox, true);
722723
// process bottom border of the last added row if there is no footer
723-
if (!isAndWasComplete) {
724+
if (!isAndWasComplete && !isFirstOnThePage) {
724725
bordersHandler.applyTopTableBorder(occupiedArea.getBBox(), layoutBox, 0 == childRenderers.size(), true, false);
725726
}
726727
}
@@ -751,7 +752,7 @@ public LayoutResult layout(LayoutContext layoutContext) {
751752
- (null == footerRenderer ? 0 : footerRenderer.getOccupiedArea().getBBox().getHeight())
752753
- (null == headerRenderer ? 0 : headerRenderer.getOccupiedArea().getBBox().getHeight() - headerRenderer.bordersHandler.getMaxBottomWidth())
753754
== 0)
754-
&& isAndWasComplete)
755+
&& (isAndWasComplete || isFirstOnThePage))
755756
? LayoutResult.NOTHING
756757
: LayoutResult.PARTIAL;
757758
if ((status == LayoutResult.NOTHING && Boolean.TRUE.equals(getPropertyAsBoolean(Property.FORCED_PLACEMENT)))

layout/src/main/java/com/itextpdf/layout/renderer/TableWidths.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -469,7 +469,7 @@ float[] fixedLayout() {
469469
firtsRow = null;
470470
}
471471

472-
if (firtsRow != null) {
472+
if (firtsRow != null && getTable().isComplete() && 0 == getTable().getLastRowBottomBorder().size()) { // only for not large tables
473473
for (int i = 0; i < numberOfColumns; i++) {
474474
if (columnWidths[i] == -1) {
475475
CellRenderer cell = firtsRow[i];
@@ -493,6 +493,13 @@ float[] fixedLayout() {
493493
processedColumns++;
494494
}
495495
}
496+
} else {
497+
for (int i = 0; i < numberOfColumns; i++) {
498+
if (columnWidths[i] != -1) {
499+
processedColumns++;
500+
remainWidth -= columnWidths[i];
501+
}
502+
}
496503
}
497504

498505
if (remainWidth > 0) {

layout/src/test/java/com/itextpdf/layout/LargeElementTest.java

Lines changed: 120 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,9 @@ This file is part of the iText (R) project.
4343
package com.itextpdf.layout;
4444

4545
import com.itextpdf.io.LogMessageConstant;
46+
import com.itextpdf.io.util.MessageFormatUtil;
4647
import com.itextpdf.kernel.color.ColorConstants;
48+
import com.itextpdf.kernel.color.DeviceGray;
4749
import com.itextpdf.kernel.geom.PageSize;
4850
import com.itextpdf.kernel.pdf.PdfDocument;
4951
import com.itextpdf.kernel.pdf.PdfWriter;
@@ -53,17 +55,18 @@ This file is part of the iText (R) project.
5355
import com.itextpdf.layout.element.Cell;
5456
import com.itextpdf.layout.element.Paragraph;
5557
import com.itextpdf.layout.element.Table;
58+
import com.itextpdf.layout.property.UnitValue;
5659
import com.itextpdf.test.ExtendedITextTest;
5760
import com.itextpdf.test.annotations.LogMessage;
5861
import com.itextpdf.test.annotations.LogMessages;
5962
import com.itextpdf.test.annotations.type.IntegrationTest;
6063
import org.junit.Assert;
6164
import org.junit.BeforeClass;
65+
import org.junit.Ignore;
6266
import org.junit.Test;
6367
import org.junit.experimental.categories.Category;
6468

6569
import java.io.IOException;
66-
import com.itextpdf.io.util.MessageFormatUtil;
6770

6871
@Category(IntegrationTest.class)
6972
public class LargeElementTest extends ExtendedITextTest {
@@ -217,7 +220,7 @@ public void largeTableWithHeaderFooterTest01C() throws IOException, InterruptedE
217220
cell = new Cell(1, 5).add(new Paragraph("Continue on next page")).setHeight(30).setBorderTop(new SolidBorder(ColorConstants.MAGENTA, 20));
218221
table.addFooterCell(cell);
219222
for (int i = 0; i < 50; i++) {
220-
table.addCell(new Cell().setBorderLeft(new SolidBorder(ColorConstants.BLUE, 0.5f)).setBorderRight(new SolidBorder(ColorConstants.BLUE, 0.5f)).setHeight(30).setBorderBottom(new SolidBorder(ColorConstants.BLUE, 2*i + 1 > 50 ? 50 : 2*i + 1)).setBorderTop(new SolidBorder(ColorConstants.GREEN, (50 - 2*i + 1 >= 0) ? 50 - 2*i + 1 : 0)).add(new Paragraph(String.valueOf(i + 1))));
223+
table.addCell(new Cell().setBorderLeft(new SolidBorder(ColorConstants.BLUE, 0.5f)).setBorderRight(new SolidBorder(ColorConstants.BLUE, 0.5f)).setHeight(30).setBorderBottom(new SolidBorder(ColorConstants.BLUE, 2 * i + 1 > 50 ? 50 : 2 * i + 1)).setBorderTop(new SolidBorder(ColorConstants.GREEN, (50 - 2 * i + 1 >= 0) ? 50 - 2 * i + 1 : 0)).add(new Paragraph(String.valueOf(i + 1))));
221224
table.flush();
222225
}
223226
table.complete();
@@ -242,7 +245,7 @@ public void largeTableWithHeaderFooterTest01D() throws IOException, InterruptedE
242245
cell = new Cell(1, 5).add(new Paragraph("Continue on next page")).setHeight(30).setBorderTop(new SolidBorder(ColorConstants.MAGENTA, 20));
243246
table.addFooterCell(cell);
244247
for (int i = 0; i < 50; i++) {
245-
table.addCell(new Cell().setBorderLeft(new SolidBorder(ColorConstants.BLUE, 0.5f)).setBorderRight(new SolidBorder(ColorConstants.BLUE, 0.5f)).setHeight(30).setBorderBottom(new SolidBorder(ColorConstants.BLUE, 2*i + 1 > 50 ? 50 : 2*i + 1)).setBorderTop(new SolidBorder(ColorConstants.GREEN, (50 - 2*i + 1 >= 0) ? 50 - 2*i + 1 : 0)).add(new Paragraph(String.valueOf(i + 1))));
248+
table.addCell(new Cell().setBorderLeft(new SolidBorder(ColorConstants.BLUE, 0.5f)).setBorderRight(new SolidBorder(ColorConstants.BLUE, 0.5f)).setHeight(30).setBorderBottom(new SolidBorder(ColorConstants.BLUE, 2 * i + 1 > 50 ? 50 : 2 * i + 1)).setBorderTop(new SolidBorder(ColorConstants.GREEN, (50 - 2 * i + 1 >= 0) ? 50 - 2 * i + 1 : 0)).add(new Paragraph(String.valueOf(i + 1))));
246249
table.flush();
247250
}
248251
table.complete();
@@ -386,6 +389,118 @@ public void largeTableWithHeaderFooterTest04() throws IOException, InterruptedEx
386389
Assert.assertNull(new CompareTool().compareByContent(outFileName, cmpFileName, destinationFolder, testName + "_diff"));
387390
}
388391

392+
@Ignore("DEVSIX-1646")
393+
@Test
394+
public void largeTableWithLayoutResultNothingTest01() throws IOException, InterruptedException {
395+
String testName = "largeTableWithLayoutResultNothingTest01.pdf";
396+
String outFileName = destinationFolder + testName;
397+
String cmpFileName = sourceFolder + "cmp_" + testName;
398+
399+
PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outFileName));
400+
Document doc = new Document(pdfDoc, PageSize.A1.rotate());
401+
402+
float[] colWidths = new float[]{300, 150, 50, 100};
403+
404+
Table table = new Table(UnitValue.createPointArray(colWidths), true);
405+
406+
int numOfColumns = colWidths.length - 1;
407+
Cell[] cells = new Cell[numOfColumns];
408+
409+
for (int i = 0; i < numOfColumns; i++) {
410+
cells[i] = new Cell(1, 1 + i % 2).add("Cell" + i);
411+
cells[i].setBorder(new SolidBorder(new DeviceGray(i / (float) numOfColumns), 10));
412+
table.addCell(cells[i]);
413+
}
414+
doc.add(table);
415+
416+
for (int i = 0; i < numOfColumns; i++) {
417+
cells[i].setBorder(new SolidBorder(new DeviceGray(i / (float) numOfColumns), 50));
418+
table.addCell(cells[i]);
419+
}
420+
table.flush();
421+
422+
for (int i = 0; i < numOfColumns; i++) {
423+
cells[i].setBorder(new SolidBorder(new DeviceGray(i / (float) numOfColumns), 1));
424+
table.addCell(cells[i]);
425+
}
426+
table.flush();
427+
428+
for (int i = 0; i < numOfColumns; i++) {
429+
cells[i].setBorder(new SolidBorder(new DeviceGray(i / (float) numOfColumns), 100));
430+
table.addCell(cells[i]);
431+
}
432+
table.flush();
433+
434+
table.complete();
435+
436+
doc.close();
437+
Assert.assertNull(new CompareTool().compareByContent(outFileName, cmpFileName, destinationFolder, testName + "_diff"));
438+
}
439+
440+
441+
@Test
442+
@LogMessages(messages = {@LogMessage(messageTemplate = LogMessageConstant.ELEMENT_DOES_NOT_FIT_AREA, count = 1)})
443+
public void largeTableWithLayoutResultNothingTest02() throws IOException, InterruptedException {
444+
String testName = "largeTableWithLayoutResultNothingTest02.pdf";
445+
String outFileName = destinationFolder + testName;
446+
String cmpFileName = sourceFolder + "cmp_" + testName;
447+
448+
PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outFileName));
449+
Document doc = new Document(pdfDoc, PageSize.A4.rotate());
450+
451+
float[] colWidths = new float[]{200, 1, 2, 4};
452+
453+
Table table = new Table(UnitValue.createPointArray(colWidths), true);
454+
doc.add(table);
455+
456+
Cell cell1 = new Cell().add("Cell1");
457+
Cell cell2 = new Cell().add("Cell2");
458+
Cell cell3 = new Cell().add("Cell3");
459+
Cell cell4 = new Cell().add("Cell4");
460+
461+
table.addCell(cell1);
462+
table.addCell(cell2);
463+
table.addCell(cell3);
464+
table.addCell(cell4);
465+
table.flush();
466+
467+
table.complete();
468+
469+
doc.close();
470+
Assert.assertNull(new CompareTool().compareByContent(outFileName, cmpFileName, destinationFolder, testName + "_diff"));
471+
}
472+
473+
@Test
474+
public void largeTableWithLayoutResultNothingTest03() throws IOException, InterruptedException {
475+
String testName = "largeTableWithLayoutResultNothingTest03.pdf";
476+
String outFileName = destinationFolder + testName;
477+
String cmpFileName = sourceFolder + "cmp_" + testName;
478+
479+
PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outFileName));
480+
Document doc = new Document(pdfDoc, PageSize.A4.rotate());
481+
482+
float[] colWidths = new float[]{200, -1, 20, 40};
483+
484+
Table table = new Table(UnitValue.createPointArray(colWidths), true);
485+
doc.add(table);
486+
487+
Cell cell1 = new Cell().add("Cell1");
488+
Cell cell2 = new Cell().add("Cell2");
489+
Cell cell3 = new Cell().add("Cell3");
490+
Cell cell4 = new Cell().add("Cell4");
491+
492+
table.addCell(cell1);
493+
table.addCell(cell2);
494+
table.addCell(cell3);
495+
table.addCell(cell4);
496+
table.flush();
497+
498+
table.complete();
499+
500+
doc.close();
501+
Assert.assertNull(new CompareTool().compareByContent(outFileName, cmpFileName, destinationFolder, testName + "_diff"));
502+
}
503+
389504
@Test
390505
public void largeEmptyTableTest() throws IOException, InterruptedException {
391506
String testName = "largeEmptyTableTest.pdf";
@@ -446,7 +561,7 @@ public void largeEmptyTableTest02() throws IOException, InterruptedException {
446561
table.addHeaderCell(new Cell().add(new Paragraph("Header" + i)));
447562
table.addFooterCell(new Cell().add(new Paragraph("Footer" + i)));
448563
}
449-
table.addCell(new Cell().add(new Paragraph("Cell" )));
564+
table.addCell(new Cell().add(new Paragraph("Cell")));
450565
table.complete();
451566
doc.add(new Table(1).setBorder(new SolidBorder(ColorConstants.ORANGE, 2)).addCell("Is my occupied area correct?"));
452567
doc.add(new AreaBreak());
@@ -467,7 +582,7 @@ public void largeEmptyTableTest02() throws IOException, InterruptedException {
467582
table.addHeaderCell(new Cell().add(new Paragraph("Header" + i)));
468583
table.addFooterCell(new Cell().add(new Paragraph("Footer" + i)));
469584
}
470-
table.addCell(new Cell().add(new Paragraph("Cell" )));
585+
table.addCell(new Cell().add(new Paragraph("Cell")));
471586
table.complete();
472587
doc.add(new Table(1).setBorder(new SolidBorder(ColorConstants.ORANGE, 2)).addCell("Is my occupied area correct?"));
473588

0 commit comments

Comments
 (0)