Skip to content

Commit 486b539

Browse files
committed
Process corners of collapsed borders according to browsers
DEVSIX-5524
1 parent 3d56594 commit 486b539

File tree

104 files changed

+938
-137
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

104 files changed

+938
-137
lines changed

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

Lines changed: 266 additions & 68 deletions
Large diffs are not rendered by default.

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,12 +64,12 @@ public SeparatedTableBorders(List<CellRenderer[]> rows, int numberOfColumns, Bor
6464
}
6565

6666
@Override
67-
protected TableBorders drawHorizontalBorder(int i, float startX, float y1, PdfCanvas canvas, float[] countedColumnWidth) {
67+
protected TableBorders drawHorizontalBorder(PdfCanvas canvas, TableBorderDescriptor borderDescriptor) {
6868
return this;
6969
}
7070

7171
@Override
72-
protected TableBorders drawVerticalBorder(int i, float startY, float x1, PdfCanvas canvas, List<Float> heights) {
72+
protected TableBorders drawVerticalBorder(PdfCanvas canvas, TableBorderDescriptor borderDescriptor) {
7373
return this;
7474
}
7575

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
/*
2+
3+
This file is part of the iText (R) project.
4+
Copyright (c) 1998-2021 iText Group NV
5+
Authors: Bruno Lowagie, Paulo Soares, et al.
6+
7+
This program is free software; you can redistribute it and/or modify
8+
it under the terms of the GNU Affero General Public License version 3
9+
as published by the Free Software Foundation with the addition of the
10+
following permission added to Section 15 as permitted in Section 7(a):
11+
FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY
12+
ITEXT GROUP. ITEXT GROUP DISCLAIMS THE WARRANTY OF NON INFRINGEMENT
13+
OF THIRD PARTY RIGHTS
14+
15+
This program is distributed in the hope that it will be useful, but
16+
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
17+
or FITNESS FOR A PARTICULAR PURPOSE.
18+
See the GNU Affero General Public License for more details.
19+
You should have received a copy of the GNU Affero General Public License
20+
along with this program; if not, see http://www.gnu.org/licenses or write to
21+
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22+
Boston, MA, 02110-1301 USA, or download the license from the following URL:
23+
http://itextpdf.com/terms-of-use/
24+
25+
The interactive user interfaces in modified source and object code versions
26+
of this program must display Appropriate Legal Notices, as required under
27+
Section 5 of the GNU Affero General Public License.
28+
29+
In accordance with Section 7(b) of the GNU Affero General Public License,
30+
a covered work must retain the producer line in every PDF that is created
31+
or manipulated using iText.
32+
33+
You can be released from the requirements of the license by purchasing
34+
a commercial license. Buying such a license is mandatory as soon as you
35+
develop commercial activities involving the iText software without
36+
disclosing the source code of your own applications.
37+
These activities include: offering paid services to customers as an ASP,
38+
serving PDFs on the fly in a web application, shipping iText with a closed
39+
source product.
40+
41+
For more information, please contact iText Software Corp. at this
42+
43+
*/
44+
package com.itextpdf.layout.renderer;
45+
46+
class TableBorderDescriptor {
47+
private int borderIndex;
48+
private float mainCoordinateStart;
49+
private float crossCoordinate;
50+
private float[] mainCoordinateWidths;
51+
52+
/**
53+
* Creates a table border descriptor which will be used while drawing the described border.
54+
*
55+
* @param borderIndex the index of the described border
56+
* @param mainCoordinateStart the border's start main-axis coordinate
57+
* @param crossCoordinate fixed cross-axis coordinate of the whole border
58+
* @param mainCoordinateWidths the sizes (widths or heights) of rows or columns depending on the type of main axis
59+
*/
60+
public TableBorderDescriptor(int borderIndex, float mainCoordinateStart, float crossCoordinate,
61+
float[] mainCoordinateWidths) {
62+
this.borderIndex = borderIndex;
63+
this.mainCoordinateStart = mainCoordinateStart;
64+
this.crossCoordinate = crossCoordinate;
65+
this.mainCoordinateWidths = mainCoordinateWidths;
66+
}
67+
68+
public int getBorderIndex() {
69+
return borderIndex;
70+
}
71+
72+
public float getMainCoordinateStart() {
73+
return mainCoordinateStart;
74+
}
75+
76+
public float getCrossCoordinate() {
77+
return crossCoordinate;
78+
}
79+
80+
public float[] getMainCoordinateWidths() {
81+
return mainCoordinateWidths;
82+
}
83+
}

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,11 @@ This file is part of the iText (R) project.
4848
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
4949
import com.itextpdf.layout.borders.Border;
5050
import com.itextpdf.layout.property.Property;
51-
import org.slf4j.Logger;
52-
import org.slf4j.LoggerFactory;
5351

5452
import java.util.ArrayList;
5553
import java.util.List;
54+
import org.slf4j.Logger;
55+
import org.slf4j.LoggerFactory;
5656

5757
abstract class TableBorders {
5858
/**
@@ -138,9 +138,9 @@ public TableBorders(List<CellRenderer[]> rows, int numberOfColumns, Border[] tab
138138
// region abstract
139139

140140
// region draw
141-
protected abstract TableBorders drawHorizontalBorder(int i, float startX, float y1, PdfCanvas canvas, float[] countedColumnWidth);
141+
protected abstract TableBorders drawHorizontalBorder(PdfCanvas canvas, TableBorderDescriptor borderDescriptor);
142142

143-
protected abstract TableBorders drawVerticalBorder(int i, float startY, float x1, PdfCanvas canvas, List<Float> heights);
143+
protected abstract TableBorders drawVerticalBorder(PdfCanvas canvas, TableBorderDescriptor borderDescriptor);
144144
// endregion
145145

146146
// region area occupation

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

Lines changed: 46 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,6 @@ This file is part of the iText (R) project.
6565
import com.itextpdf.layout.property.UnitValue;
6666
import com.itextpdf.layout.property.VerticalAlignment;
6767
import com.itextpdf.layout.tagging.LayoutTaggingHelper;
68-
import org.slf4j.Logger;
69-
import org.slf4j.LoggerFactory;
7068

7169
import java.util.ArrayDeque;
7270
import java.util.ArrayList;
@@ -75,6 +73,8 @@ This file is part of the iText (R) project.
7573
import java.util.HashMap;
7674
import java.util.List;
7775
import java.util.Map;
76+
import org.slf4j.Logger;
77+
import org.slf4j.LoggerFactory;
7878

7979
/**
8080
* This class represents the {@link IRenderer renderer} object for a {@link Table}
@@ -781,7 +781,7 @@ public LayoutResult layout(LayoutContext layoutContext) {
781781
// And now, when we possess such knowledge, we are performing the second attempt, but we need to nullify results
782782
// from the previous attempt
783783
if (bordersHandler instanceof CollapsedTableBorders) {
784-
((CollapsedTableBorders)bordersHandler).setBottomBorderCollapseWith(null);
784+
((CollapsedTableBorders) bordersHandler).setBottomBorderCollapseWith(null, null);
785785
}
786786
bordersHandler.collapseTableWithFooter(footerRenderer.bordersHandler, hasContent || 0 != childRenderers.size());
787787

@@ -1050,10 +1050,6 @@ public LayoutResult layout(LayoutContext layoutContext) {
10501050
}
10511051
}
10521052
} else {
1053-
// the bottom border should be processed and placed lately
1054-
if (0 != heights.size()) {
1055-
heights.set(heights.size() - 1, heights.get(heights.size() - 1) - bottomTableBorderWidth / 2);
1056-
}
10571053
if (null == footerRenderer) {
10581054
if (0 != childRenderers.size()) {
10591055
bordersHandler.applyBottomTableBorder(occupiedArea.getBBox(), layoutBox, 0 == childRenderers.size(), false, true);
@@ -1460,7 +1456,7 @@ private void drawBorders(DrawContext drawContext, boolean hasHeader, boolean has
14601456
}
14611457

14621458

1463-
// process halves of the borders here
1459+
// process halves of horizontal bounding borders
14641460
if (childRenderers.size() == 0) {
14651461
Border[] borders = bordersHandler.tableBoundingBorders;
14661462
if (null != borders[0]) {
@@ -1492,56 +1488,72 @@ private void drawBorders(DrawContext drawContext, boolean hasHeader, boolean has
14921488

14931489
if (bordersHandler instanceof CollapsedTableBorders) {
14941490
if (hasFooter) {
1495-
((CollapsedTableBorders) bordersHandler).setBottomBorderCollapseWith(footerRenderer.bordersHandler.getFirstHorizontalBorder());
1491+
((CollapsedTableBorders) bordersHandler).setBottomBorderCollapseWith(
1492+
footerRenderer.bordersHandler.getFirstHorizontalBorder(),
1493+
((CollapsedTableBorders) footerRenderer.bordersHandler)
1494+
.getVerticalBordersCrossingTopHorizontalBorder());
14961495
} else if (isBottomTablePart) {
1497-
((CollapsedTableBorders) bordersHandler).setBottomBorderCollapseWith(null);
1496+
((CollapsedTableBorders) bordersHandler).setBottomBorderCollapseWith(null, null);
14981497
}
14991498
}
15001499
// we do not need to fix top border, because either this is header or the top border has been already written
15011500
float y1 = startY;
1501+
1502+
float[] heightsArray = new float[heights.size()];
1503+
for (int j = 0; j < heights.size(); j++) {
1504+
heightsArray[j] = heights.get(j);
1505+
}
1506+
1507+
// draw vertical borders
1508+
float x1 = startX;
1509+
for (int i = 0; i <= bordersHandler.getNumberOfColumns(); i++) {
1510+
bordersHandler.drawVerticalBorder(drawContext.getCanvas(),
1511+
new TableBorderDescriptor(i, startY, x1, heightsArray));
1512+
if (i < countedColumnWidth.length) {
1513+
x1 += countedColumnWidth[i];
1514+
}
1515+
}
1516+
1517+
// draw horizontal borders
1518+
1519+
// draw top border
15021520
if (isFooterRendererOfLargeTable) {
1503-
bordersHandler.drawHorizontalBorder(0, startX, y1, drawContext.getCanvas(), countedColumnWidth);
1521+
bordersHandler.drawHorizontalBorder(drawContext.getCanvas(), new TableBorderDescriptor(0, startX, y1,
1522+
countedColumnWidth));
15041523
}
1505-
if (0 != heights.size()) {
1524+
if (isTopTablePart) {
1525+
bordersHandler.drawHorizontalBorder(drawContext.getCanvas(), new TableBorderDescriptor(0, startX, startY,
1526+
countedColumnWidth));
1527+
}
1528+
1529+
// draw inner borders
1530+
if (!heights.isEmpty()) {
15061531
y1 -= (float) heights.get(0);
15071532
}
15081533
for (int i = 1; i < heights.size(); i++) {
1509-
bordersHandler.drawHorizontalBorder(i, startX, y1, drawContext.getCanvas(), countedColumnWidth);
1534+
bordersHandler.drawHorizontalBorder(drawContext.getCanvas(),
1535+
new TableBorderDescriptor(i, startX, y1, countedColumnWidth));
15101536
if (i < heights.size()) {
15111537
y1 -= (float) heights.get(i);
15121538
}
15131539
}
1514-
if (!isBottomTablePart && isComplete) {
1515-
bordersHandler.drawHorizontalBorder(heights.size(), startX, y1, drawContext.getCanvas(), countedColumnWidth);
1516-
}
15171540

1518-
float x1 = startX;
1519-
if (countedColumnWidth.length > 0) {
1520-
x1 += countedColumnWidth[0];
1521-
}
1522-
for (int i = 1; i < bordersHandler.getNumberOfColumns(); i++) {
1523-
bordersHandler.drawVerticalBorder(i, startY, x1, drawContext.getCanvas(), heights);
1524-
if (i < countedColumnWidth.length) {
1525-
x1 += countedColumnWidth[i];
1526-
}
1541+
// draw bottom border
1542+
// TODO DEVSIX-5867 Check hasFooter, so that two footers are not drawn
1543+
if (!isBottomTablePart && isComplete) {
1544+
bordersHandler.drawHorizontalBorder(drawContext.getCanvas(),
1545+
new TableBorderDescriptor(heights.size(), startX, y1, countedColumnWidth));
15271546
}
15281547

1529-
// Draw bounding borders. Vertical borders are the last to draw in order to collapse with header / footer
1530-
if (isTopTablePart) {
1531-
bordersHandler.drawHorizontalBorder(0, startX, startY, drawContext.getCanvas(), countedColumnWidth);
1532-
}
15331548
//!isLastRendererForModelElement is a check that this is a split render. This is the case with the splitting of
15341549
// one cell when part of the cell moves to the next page. Therefore, if such a splitting occurs, a bottom border
15351550
// should be drawn. However, this should not be done for empty renderers that are also created during splitting,
15361551
// but this splitting, if the table does not fit on the page and the next cell is added to the next page.
15371552
// In this case, this code should not be processed, since the border in the above code has already been drawn.
15381553
if (isBottomTablePart && (isComplete || (!isLastRendererForModelElement && !isEmptyTableRenderer()))) {
1539-
bordersHandler.drawHorizontalBorder(heights.size(), startX, y1, drawContext.getCanvas(), countedColumnWidth);
1554+
bordersHandler.drawHorizontalBorder(drawContext.getCanvas(), new TableBorderDescriptor(
1555+
heights.size(), startX, y1, countedColumnWidth));
15401556
}
1541-
// draw left
1542-
bordersHandler.drawVerticalBorder(0, startY, startX, drawContext.getCanvas(), heights);
1543-
// draw right
1544-
bordersHandler.drawVerticalBorder(bordersHandler.getNumberOfColumns(), startY, x1, drawContext.getCanvas(), heights);
15451557

15461558
if (isTagged) {
15471559
drawContext.getCanvas().closeTag();

0 commit comments

Comments
 (0)