Skip to content

Commit 0b593d9

Browse files
Fix handling of overflow_x in case of alignment of overflowed content
DEVSIX-1563
1 parent 0854f99 commit 0b593d9

File tree

10 files changed

+115
-56
lines changed

10 files changed

+115
-56
lines changed

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

Lines changed: 32 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -852,10 +852,9 @@ public void drawChildren(DrawContext drawContext) {
852852
List<IRenderer> waitingRenderers = new ArrayList<>();
853853
for (IRenderer child : childRenderers) {
854854
Transform transformProp = child.<Transform>getProperty(Property.TRANSFORM);
855-
Border outlineProp = child.<Border>getProperty(Property.OUTLINE);
856855
RootRenderer rootRenderer = getRootRenderer();
857856
List<IRenderer> waiting = (rootRenderer != null && !rootRenderer.waitingDrawingElements.contains(child)) ? rootRenderer.waitingDrawingElements : waitingRenderers;
858-
processWaitingDrawing(child, transformProp, outlineProp, waiting);
857+
processWaitingDrawing(child, transformProp, waiting);
859858
if (!FloatingHelper.isRendererFloating(child) && transformProp == null) {
860859
child.draw(drawContext);
861860
}
@@ -865,36 +864,6 @@ public void drawChildren(DrawContext drawContext) {
865864
}
866865
}
867866

868-
static void processWaitingDrawing(IRenderer child, Transform transformProp, Border outlineProp, List<IRenderer> waitingDrawing) {
869-
if (FloatingHelper.isRendererFloating(child) || transformProp != null) {
870-
waitingDrawing.add(child);
871-
}
872-
if (outlineProp != null && child instanceof AbstractRenderer) {
873-
AbstractRenderer abstractChild = (AbstractRenderer) child;
874-
if (abstractChild.isRelativePosition())
875-
abstractChild.applyRelativePositioningTranslation(false);
876-
Div outlines = new Div();
877-
outlines.getAccessibilityProperties().setRole(null);
878-
if (transformProp != null)
879-
outlines.setProperty(Property.TRANSFORM, transformProp);
880-
outlines.setProperty(Property.BORDER, outlineProp);
881-
float offset = outlines.<Border>getProperty(Property.BORDER).getWidth();
882-
if (abstractChild.getPropertyAsFloat(Property.OUTLINE_OFFSET) != null)
883-
offset += (float) abstractChild.getPropertyAsFloat(Property.OUTLINE_OFFSET);
884-
DivRenderer div = new DivRenderer(outlines);
885-
div.setParent(abstractChild.getParent());
886-
Rectangle divOccupiedArea = abstractChild.applyMargins(abstractChild.occupiedArea.clone().getBBox(), false).moveLeft(offset).moveDown(offset);
887-
divOccupiedArea.setWidth(divOccupiedArea.getWidth() + 2 * offset).setHeight(divOccupiedArea.getHeight() + 2 * offset);
888-
div.occupiedArea = new LayoutArea(abstractChild.getOccupiedArea().getPageNumber(), divOccupiedArea);
889-
float outlineWidth = div.<Border>getProperty(Property.BORDER).getWidth();
890-
if (divOccupiedArea.getWidth() >= outlineWidth * 2 && divOccupiedArea.getHeight() >= outlineWidth * 2) {
891-
waitingDrawing.add(div);
892-
}
893-
if (abstractChild.isRelativePosition())
894-
abstractChild.applyRelativePositioningTranslation(true);
895-
}
896-
}
897-
898867
/**
899868
* Performs the drawing operation for the border of this renderer, if
900869
* defined by any of the {@link Property#BORDER} values in either the layout
@@ -1074,6 +1043,37 @@ static boolean isBorderBoxSizing(IRenderer renderer) {
10741043
return boxSizing != null && boxSizing.equals(BoxSizingPropertyValue.BORDER_BOX);
10751044
}
10761045

1046+
static void processWaitingDrawing(IRenderer child, Transform transformProp, List<IRenderer> waitingDrawing) {
1047+
if (FloatingHelper.isRendererFloating(child) || transformProp != null) {
1048+
waitingDrawing.add(child);
1049+
}
1050+
Border outlineProp = child.<Border>getProperty(Property.OUTLINE);
1051+
if (outlineProp != null && child instanceof AbstractRenderer) {
1052+
AbstractRenderer abstractChild = (AbstractRenderer) child;
1053+
if (abstractChild.isRelativePosition())
1054+
abstractChild.applyRelativePositioningTranslation(false);
1055+
Div outlines = new Div();
1056+
outlines.getAccessibilityProperties().setRole(null);
1057+
if (transformProp != null)
1058+
outlines.setProperty(Property.TRANSFORM, transformProp);
1059+
outlines.setProperty(Property.BORDER, outlineProp);
1060+
float offset = outlines.<Border>getProperty(Property.BORDER).getWidth();
1061+
if (abstractChild.getPropertyAsFloat(Property.OUTLINE_OFFSET) != null)
1062+
offset += (float) abstractChild.getPropertyAsFloat(Property.OUTLINE_OFFSET);
1063+
DivRenderer div = new DivRenderer(outlines);
1064+
div.setParent(abstractChild.getParent());
1065+
Rectangle divOccupiedArea = abstractChild.applyMargins(abstractChild.occupiedArea.clone().getBBox(), false).moveLeft(offset).moveDown(offset);
1066+
divOccupiedArea.setWidth(divOccupiedArea.getWidth() + 2 * offset).setHeight(divOccupiedArea.getHeight() + 2 * offset);
1067+
div.occupiedArea = new LayoutArea(abstractChild.getOccupiedArea().getPageNumber(), divOccupiedArea);
1068+
float outlineWidth = div.<Border>getProperty(Property.BORDER).getWidth();
1069+
if (divOccupiedArea.getWidth() >= outlineWidth * 2 && divOccupiedArea.getHeight() >= outlineWidth * 2) {
1070+
waitingDrawing.add(div);
1071+
}
1072+
if (abstractChild.isRelativePosition())
1073+
abstractChild.applyRelativePositioningTranslation(true);
1074+
}
1075+
}
1076+
10771077
/**
10781078
* Retrieves element's fixed content box width, if it's set.
10791079
* Takes into account {@link Property#BOX_SIZING}, {@link Property#MIN_WIDTH},

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

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -215,9 +215,7 @@ public LayoutResult layout(LayoutContext layoutContext) {
215215
occupiedArea.setBBox(Rectangle.getCommonRectangle(occupiedArea.getBBox(), layoutBox));
216216
} else if (result.getOccupiedArea() != null && result.getStatus() != LayoutResult.NOTHING) {
217217
occupiedArea.setBBox(Rectangle.getCommonRectangle(occupiedArea.getBBox(), result.getOccupiedArea().getBBox()));
218-
if (occupiedArea.getBBox().getWidth() > layoutBox.getWidth() && !(null == overflowX || OverflowPropertyValue.FIT.equals(overflowX))) {
219-
occupiedArea.getBBox().setWidth(layoutBox.getWidth());
220-
}
218+
fixOccupiedAreaWidthAndXPositionIfOverflowed(overflowX, layoutBox);
221219
}
222220

223221
// On page split, content will be drawn on next page, i.e. under all floats on this page
@@ -328,9 +326,7 @@ public LayoutResult layout(LayoutContext layoutContext) {
328326
if (result.getOccupiedArea() != null) {
329327
if (!FloatingHelper.isRendererFloating(childRenderer)) { // this check is needed only if margins collapsing is enabled
330328
occupiedArea.setBBox(Rectangle.getCommonRectangle(occupiedArea.getBBox(), result.getOccupiedArea().getBBox()));
331-
if (occupiedArea.getBBox().getWidth() > layoutBox.getWidth() && !(null == overflowX || OverflowPropertyValue.FIT.equals(overflowX))) {
332-
occupiedArea.getBBox().setWidth(layoutBox.getWidth());
333-
}
329+
fixOccupiedAreaWidthAndXPositionIfOverflowed(overflowX, layoutBox);
334330
}
335331
}
336332
if (marginsCollapsingEnabled) {
@@ -738,7 +734,7 @@ void applyWidth(Rectangle parentBBox, Float blockWidth, OverflowPropertyValue ov
738734
Float rotation = this.getPropertyAsFloat(Property.ROTATION_ANGLE);
739735

740736
if (blockWidth != null && (
741-
blockWidth < parentBBox.getWidth() ||
737+
blockWidth < parentBBox.getWidth() ||
742738
isPositioned() ||
743739
rotation != null ||
744740
(null != overflowX && !OverflowPropertyValue.FIT.equals(overflowX)))) {
@@ -759,7 +755,7 @@ boolean applyMaxHeight(Rectangle parentBBox, Float blockMaxHeight, MarginsCollap
759755
return false;
760756
}
761757
boolean wasHeightClipped = false;
762-
if (blockMaxHeight < parentBBox.getHeight()) {
758+
if (blockMaxHeight <= parentBBox.getHeight()) {
763759
wasHeightClipped = true;
764760
}
765761
float heightDelta = parentBBox.getHeight() - (float) blockMaxHeight;
@@ -780,6 +776,16 @@ float getOverflowPartHeight(OverflowPropertyValue overflowY, Rectangle parentBox
780776
return difference;
781777
}
782778

779+
void fixOccupiedAreaWidthAndXPositionIfOverflowed(OverflowPropertyValue overflowX, Rectangle layoutBox) {
780+
if (overflowX == null || OverflowPropertyValue.FIT.equals(overflowX)) {
781+
return;
782+
}
783+
784+
if ((occupiedArea.getBBox().getWidth() > layoutBox.getWidth() || occupiedArea.getBBox().getLeft() < layoutBox.getLeft())) {
785+
occupiedArea.getBBox().setX(layoutBox.getX()).setWidth(layoutBox.getWidth());
786+
}
787+
}
788+
783789
protected float applyBordersPaddingsMargins(Rectangle parentBBox, Border[] borders, UnitValue[] paddings) {
784790
float parentWidth = parentBBox.getWidth();
785791

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,9 +96,8 @@ public void addChild(IRenderer renderer) {
9696
@Override
9797
protected void flushSingleRenderer(IRenderer resultRenderer) {
9898
Transform transformProp = resultRenderer.<Transform>getProperty(Property.TRANSFORM);
99-
Border outlineProp = resultRenderer.<Border>getProperty(Property.OUTLINE);
10099
if (!waitingDrawingElements.contains(resultRenderer)) {
101-
processWaitingDrawing(resultRenderer, transformProp, outlineProp, waitingDrawingElements);
100+
processWaitingDrawing(resultRenderer, transformProp, waitingDrawingElements);
102101
if (FloatingHelper.isRendererFloating(resultRenderer) || transformProp != null)
103102
return;
104103
}

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,9 +118,8 @@ protected LayoutArea updateCurrentArea(LayoutResult overflowResult) {
118118

119119
protected void flushSingleRenderer(IRenderer resultRenderer) {
120120
Transform transformProp = resultRenderer.<Transform>getProperty(Property.TRANSFORM);
121-
Border outlineProp = resultRenderer.<Border>getProperty(Property.OUTLINE);
122121
if (!waitingDrawingElements.contains(resultRenderer)) {
123-
processWaitingDrawing(resultRenderer, transformProp, outlineProp, waitingDrawingElements);
122+
processWaitingDrawing(resultRenderer, transformProp, waitingDrawingElements);
124123
if (FloatingHelper.isRendererFloating(resultRenderer) || transformProp != null)
125124
return;
126125
}

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

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,6 @@ This file is part of the iText (R) project.
6666

6767
import java.util.ArrayList;
6868
import java.util.Collections;
69-
import java.util.HashMap;
7069
import java.util.List;
7170

7271
/**
@@ -314,9 +313,7 @@ public LayoutResult layout(LayoutContext layoutContext) {
314313
} else {
315314
if (Boolean.TRUE.equals(getPropertyAsBoolean(Property.FORCED_PLACEMENT))) {
316315
occupiedArea.setBBox(Rectangle.getCommonRectangle(occupiedArea.getBBox(), currentRenderer.getOccupiedArea().getBBox()));
317-
if (occupiedArea.getBBox().getWidth() > layoutBox.getWidth() && !(null == overflowX || OverflowPropertyValue.FIT.equals(overflowX))) {
318-
occupiedArea.getBBox().setWidth(layoutBox.getWidth());
319-
}
316+
fixOccupiedAreaWidthAndXPositionIfOverflowed(overflowX, layoutBox);
320317
parent.setProperty(Property.FULL, true);
321318
lines.add(currentRenderer);
322319
// Force placement of children we have and do not force placement of the others
@@ -344,9 +341,7 @@ public LayoutResult layout(LayoutContext layoutContext) {
344341
}
345342
if (lineHasContent) {
346343
occupiedArea.setBBox(Rectangle.getCommonRectangle(occupiedArea.getBBox(), processedRenderer.getOccupiedArea().getBBox()));
347-
if (occupiedArea.getBBox().getWidth() > layoutBox.getWidth() && !(null == overflowX || OverflowPropertyValue.FIT.equals(overflowX))) {
348-
occupiedArea.getBBox().setWidth(layoutBox.getWidth());
349-
}
344+
fixOccupiedAreaWidthAndXPositionIfOverflowed(overflowX, layoutBox);
350345
}
351346
firstLineInBox = false;
352347

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,7 @@ public LayoutResult layout(LayoutContext layoutContext) {
273273

274274
applyFixedXOrYPosition(true, layoutBox);
275275

276-
if (null != blockMaxHeight && blockMaxHeight < layoutBox.getHeight()
276+
if (null != blockMaxHeight && blockMaxHeight <= layoutBox.getHeight()
277277
&& !Boolean.TRUE.equals(getPropertyAsBoolean(Property.FORCED_PLACEMENT))) {
278278
layoutBox.moveUp(layoutBox.getHeight() - (float) blockMaxHeight).setHeight((float) blockMaxHeight);
279279
wasHeightClipped = true;

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

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

4545
import com.itextpdf.io.font.constants.StandardFonts;
46+
import com.itextpdf.io.image.ImageDataFactory;
4647
import com.itextpdf.kernel.colors.ColorConstants;
4748
import com.itextpdf.kernel.font.PdfFontFactory;
4849
import com.itextpdf.kernel.pdf.PdfDocument;
4950
import com.itextpdf.kernel.pdf.PdfWriter;
5051
import com.itextpdf.kernel.utils.CompareTool;
52+
import com.itextpdf.layout.borders.SolidBorder;
53+
import com.itextpdf.layout.element.Div;
54+
import com.itextpdf.layout.element.Image;
5155
import com.itextpdf.layout.element.Paragraph;
5256
import com.itextpdf.layout.element.Text;
57+
import com.itextpdf.layout.property.OverflowPropertyValue;
58+
import com.itextpdf.layout.property.Property;
59+
import com.itextpdf.layout.property.TextAlignment;
5360
import com.itextpdf.test.ExtendedITextTest;
5461
import com.itextpdf.test.annotations.type.IntegrationTest;
62+
import java.io.IOException;
5563
import org.junit.Assert;
5664
import org.junit.BeforeClass;
5765
import org.junit.Test;
5866
import org.junit.experimental.categories.Category;
5967

60-
import java.io.IOException;
61-
6268
@Category(IntegrationTest.class)
63-
public class OverflowTest extends ExtendedITextTest{
69+
public class OverflowTest extends ExtendedITextTest {
6470

65-
public static final String sourceFolder = "./src/test/resources/com/itextpdf/layout/OverflowTest/";
6671
public static final String destinationFolder = "./target/test/com/itextpdf/layout/OverflowTest/";
72+
public static final String sourceFolder = "./src/test/resources/com/itextpdf/layout/OverflowTest/";
6773

6874
@BeforeClass
6975
public static void beforeClass() {
@@ -143,4 +149,58 @@ public void textOverflowTest04() throws IOException, InterruptedException {
143149

144150
Assert.assertNull(new CompareTool().compareByContent(outFileName, cmpFileName, destinationFolder, "diff"));
145151
}
152+
153+
@Test
154+
public void alignedInlineContentOverflowHiddenTest01() throws IOException, InterruptedException {
155+
String outFileName = destinationFolder + "alignedInlineContentOverflowHiddenTest01.pdf";
156+
String cmpFileName = sourceFolder + "cmp_alignedInlineContentOverflowHiddenTest01.pdf";
157+
String imgPath = sourceFolder + "itis.jpg";
158+
PdfDocument pdfDocument = new PdfDocument(new PdfWriter(outFileName));
159+
160+
Document document = new Document(pdfDocument);
161+
162+
Div div = new Div().setHeight(150f).setWidth(150f).setBorder(new SolidBorder(5f));
163+
div.setProperty(Property.OVERFLOW_X, OverflowPropertyValue.HIDDEN);
164+
div.setProperty(Property.OVERFLOW_Y, OverflowPropertyValue.HIDDEN);
165+
166+
Image img = new Image(ImageDataFactory.create(imgPath));
167+
Paragraph p = new Paragraph().setTextAlignment(TextAlignment.CENTER);
168+
169+
p.setProperty(Property.OVERFLOW_X, OverflowPropertyValue.VISIBLE);
170+
p.setProperty(Property.OVERFLOW_Y, OverflowPropertyValue.VISIBLE);
171+
img.setProperty(Property.OVERFLOW_X, OverflowPropertyValue.VISIBLE);
172+
img.setProperty(Property.OVERFLOW_Y, OverflowPropertyValue.VISIBLE);
173+
document.add(
174+
div.add(
175+
p.add(img)));
176+
177+
document.close();
178+
179+
Assert.assertNull(new CompareTool().compareByContent(outFileName, cmpFileName, destinationFolder, "diff"));
180+
}
181+
182+
@Test
183+
public void alignedInlineContentOverflowHiddenTest02() throws IOException, InterruptedException {
184+
String outFileName = destinationFolder + "alignedInlineContentOverflowHiddenTest02.pdf";
185+
String cmpFileName = sourceFolder + "cmp_alignedInlineContentOverflowHiddenTest02.pdf";
186+
String imgPath = sourceFolder + "itis.jpg";
187+
PdfDocument pdfDocument = new PdfDocument(new PdfWriter(outFileName));
188+
189+
Document document = new Document(pdfDocument);
190+
191+
Image img = new Image(ImageDataFactory.create(imgPath));
192+
Paragraph p = new Paragraph()
193+
.setTextAlignment(TextAlignment.CENTER).setHeight(150f).setWidth(150f).setBorder(new SolidBorder(5f));
194+
p.setProperty(Property.OVERFLOW_X, OverflowPropertyValue.HIDDEN);
195+
p.setProperty(Property.OVERFLOW_Y, OverflowPropertyValue.HIDDEN);
196+
197+
img.setProperty(Property.OVERFLOW_X, OverflowPropertyValue.VISIBLE);
198+
img.setProperty(Property.OVERFLOW_Y, OverflowPropertyValue.VISIBLE);
199+
document.add(
200+
p.add(img));
201+
202+
document.close();
203+
204+
Assert.assertNull(new CompareTool().compareByContent(outFileName, cmpFileName, destinationFolder, "diff"));
205+
}
146206
}
12.3 KB
Loading

0 commit comments

Comments
 (0)