Skip to content

Commit 8c1249a

Browse files
committed
Improve large tables processing. Add tests.
Process large tables on different areas the same way as usual tables. Process large tables with custom width. Prohibit adding new content to completed large table. Remove last flushed row group from completed table. Fix a test. DEVSIX-1646
1 parent 1216089 commit 8c1249a

14 files changed

+274
-56
lines changed

kernel/src/main/java/com/itextpdf/kernel/PdfException.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ public class PdfException extends RuntimeException {
6767
public static final String BadCertificateAndKey = "Bad public key certificate and/or private key.";
6868
public static final String BadUserPassword = "Bad user password. Password is not provided or wrong password provided. Correct password should be passed to PdfReader constructor with properties. See ReaderProperties#setPassword() method.";
6969

70+
public static final String CannotAddCellToCompletedLargeTable = "The large table was completed. It's prohibited to use it anymore. Created different Table instance instead.";
7071
public static final String CannotAddKidToTheFlushedElement = "Cannot add kid to the flushed element.";
7172
public static final String CannotAddNonDictionaryExtGStateToResources1 = "Cannot add graphic state to resources. The PdfObject type is {0}, but should be PdfDictionary.";
7273
public static final String CannotAddNonDictionaryPatternToResources1 = "Cannot add pattern to resources. The PdfObject type is {0}, but should be PdfDictionary or PdfStream.";

layout/src/main/java/com/itextpdf/layout/element/Table.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ This file is part of the iText (R) project.
4343
*/
4444
package com.itextpdf.layout.element;
4545

46+
import com.itextpdf.kernel.PdfException;
4647
import com.itextpdf.kernel.pdf.PdfName;
4748
import com.itextpdf.kernel.pdf.tagutils.AccessibilityProperties;
4849
import com.itextpdf.layout.Document;
@@ -579,6 +580,9 @@ public Table startNewRow() {
579580
* @return this element
580581
*/
581582
public Table addCell(Cell cell) {
583+
if (isComplete && null != lastAddedRow) {
584+
throw new PdfException(PdfException.CannotAddCellToCompletedLargeTable);
585+
}
582586
// Try to find first empty slot in table.
583587
// We shall not use colspan or rowspan, 1x1 will be enough.
584588
while (true) {
@@ -707,7 +711,16 @@ public IRenderer getRenderer() {
707711
}
708712
// In case of large tables, we only add to the renderer the cells from complete row groups,
709713
// for incomplete ones we may have problem with partial rendering because of cross-dependency.
710-
lastAddedRowGroups = isComplete ? null : getRowGroups();
714+
if (isComplete) {
715+
// if table was large we need to remove the last flushed group of rows, so we need to update lastAddedRowGroups
716+
if (null != lastAddedRow && 0 != rows.size()) {
717+
List<RowRange> allRows = new ArrayList<>();
718+
allRows.add(new RowRange(rowWindowStart, rowWindowStart + rows.size() - 1));
719+
lastAddedRowGroups = allRows;
720+
}
721+
} else {
722+
lastAddedRowGroups = getRowGroups();
723+
}
711724
if (isComplete) {
712725
return new TableRenderer(this, new RowRange(rowWindowStart, rowWindowStart + rows.size() - 1));
713726
} else {

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1302,11 +1302,11 @@ void updateMinHeight(UnitValue updatedMinHeight) {
13021302
setProperty(Property.MIN_HEIGHT, updatedMinHeight);
13031303
}
13041304

1305-
protected Float retrieveUnitValue(float basePercentValue, int property) {
1305+
protected Float retrieveUnitValue(float baseValue, int property) {
13061306
UnitValue value = this.<UnitValue>getProperty(property);
13071307
if (value != null) {
13081308
if (value.getUnitType() == UnitValue.PERCENT) {
1309-
return value.getValue() * basePercentValue / 100;
1309+
return baseValue * value.getValue() / 100;
13101310
} else {
13111311
assert value.getUnitType() == UnitValue.POINT;
13121312
return value.getValue();

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

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,12 +57,13 @@ This file is part of the iText (R) project.
5757
import com.itextpdf.kernel.pdf.tagutils.AccessibilityProperties;
5858
import com.itextpdf.kernel.pdf.tagutils.IAccessibleElement;
5959
import com.itextpdf.kernel.pdf.tagutils.TagTreePointer;
60+
import com.itextpdf.layout.element.Cell;
61+
import com.itextpdf.layout.element.Table;
6062
import com.itextpdf.layout.property.Background;
6163
import com.itextpdf.layout.property.HorizontalAlignment;
6264
import com.itextpdf.layout.property.ListNumberingType;
6365
import com.itextpdf.layout.property.Property;
6466
import com.itextpdf.layout.border.Border;
65-
import com.itextpdf.layout.element.Cell;
6667
import com.itextpdf.layout.property.TextAlignment;
6768
import com.itextpdf.layout.property.TransparentColor;
6869
import com.itextpdf.layout.property.Underline;
@@ -252,9 +253,12 @@ private static void applyBlockLevelLayoutAttributes(PdfName role, AbstractRender
252253
}
253254

254255
if (role.equals(PdfName.TH) || role.equals(PdfName.TD) || role.equals(PdfName.Table)) {
255-
UnitValue width = renderer.<UnitValue>getProperty(Property.WIDTH);
256-
if (width != null && width.isPointValue()) {
257-
attributes.put(PdfName.Width, new PdfNumber(width.getValue()));
256+
// For large tables the width can be changed from flush to flush so the Width attribute shouldn't be applied
257+
if (renderer instanceof TableRenderer && ((Table) renderer.getModelElement()).isComplete()) {
258+
UnitValue width = renderer.<UnitValue>getProperty(Property.WIDTH);
259+
if (width != null && width.isPointValue()) {
260+
attributes.put(PdfName.Width, new PdfNumber(width.getValue()));
261+
}
258262
}
259263

260264
Float height = renderer.getPropertyAsFloat(Property.HEIGHT);

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -462,7 +462,7 @@ float[] fixedLayout() {
462462
CellRenderer[] firtsRow;
463463
if (tableRenderer.headerRenderer != null && tableRenderer.headerRenderer.rows.size() > 0) {
464464
firtsRow = tableRenderer.headerRenderer.rows.get(0);
465-
} else if (tableRenderer.rows.size() > 0) {
465+
} else if (tableRenderer.rows.size() > 0 && getTable().isComplete() && 0 == getTable().getLastRowBottomBorder().size()) {
466466
firtsRow = tableRenderer.rows.get(0);
467467
} else {
468468
//most likely it is large table
@@ -536,6 +536,11 @@ private void calculateTableWidth(float availableWidth, boolean calculateTableMax
536536
.<String>getProperty(Property.TABLE_LAYOUT, "auto").toLowerCase());
537537
UnitValue width = tableRenderer.<UnitValue>getProperty(Property.WIDTH);
538538
if (fixedTableLayout && width != null && width.getValue() >= 0) {
539+
if (0 != getTable().getLastRowBottomBorder().size()) {
540+
width = getTable().getWidth();
541+
} else if (!getTable().isComplete() && null != getTable().getWidth() && getTable().getWidth().isPercentValue()) {
542+
getTable().setWidth(tableRenderer.retrieveUnitValue(availableWidth, Property.WIDTH));
543+
}
539544
fixedTableWidth = true;
540545
tableWidth = (float) retrieveTableWidth(width, availableWidth);
541546
layoutMinWidth = width.isPercentValue() ? 0 : tableWidth;

0 commit comments

Comments
 (0)