Skip to content

Commit d9a9674

Browse files
author
Vitali Prudnikovich
committed
Discard FORCED_PLACEMENT property of a block renderer after some child is rendered
DEVSIX-6658
1 parent 739cba5 commit d9a9674

File tree

11 files changed

+36
-15
lines changed

11 files changed

+36
-15
lines changed

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

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,10 @@ public LayoutResult layout(LayoutContext layoutContext) {
184184
// the first renderer (one of childRenderers or their children) to produce LayoutResult.NOTHING
185185
IRenderer causeOfNothing = null;
186186
boolean anythingPlaced = false;
187+
// We have to remember initial FORCED_PLACEMENT property of this renderer to use it later
188+
// to define if rotated content should be placed or not
189+
final boolean initialForcePlacementForRotationAdjustments =
190+
Boolean.TRUE.equals(getPropertyAsBoolean(Property.FORCED_PLACEMENT));
187191
for (int childPos = 0; childPos < childRenderers.size(); childPos++) {
188192
IRenderer childRenderer = childRenderers.get(childPos);
189193
LayoutResult result;
@@ -334,6 +338,7 @@ public LayoutResult layout(LayoutContext layoutContext) {
334338
}
335339
}
336340
anythingPlaced = anythingPlaced || result.getStatus() != LayoutResult.NOTHING;
341+
handleForcedPlacement(anythingPlaced);
337342

338343
// The second condition check (after &&) is needed only if margins collapsing is enabled
339344
if (result.getOccupiedArea() != null && (!FloatingHelper.isRendererFloating(childRenderer) || includeFloatsInOccupiedArea)) {
@@ -373,7 +378,8 @@ public LayoutResult layout(LayoutContext layoutContext) {
373378
}
374379

375380
int layoutResult = LayoutResult.FULL;
376-
boolean processOverflowedFloats = !waitingOverflowFloatRenderers.isEmpty() && !wasHeightClipped && !Boolean.TRUE.equals(getPropertyAsBoolean(Property.FORCED_PLACEMENT));
381+
boolean processOverflowedFloats = !waitingOverflowFloatRenderers.isEmpty() && !wasHeightClipped &&
382+
!Boolean.TRUE.equals(getPropertyAsBoolean(Property.FORCED_PLACEMENT));
377383

378384
AbstractRenderer overflowRenderer = null;
379385
if (!includeFloatsInOccupiedArea || !processOverflowedFloats) {
@@ -453,7 +459,7 @@ public LayoutResult layout(LayoutContext layoutContext) {
453459
LoggerFactory.getLogger(getClass())
454460
.warn(MessageFormatUtil.format(LayoutLogMessageConstant.ELEMENT_DOES_NOT_FIT_AREA,
455461
"It fits by height so it will be forced placed"));
456-
} else if (!Boolean.TRUE.equals(getPropertyAsBoolean(Property.FORCED_PLACEMENT))) {
462+
} else if (!initialForcePlacementForRotationAdjustments) {
457463
floatRendererAreas.retainAll(nonChildFloatingRendererAreas);
458464
return new MinMaxWidthLayoutResult(LayoutResult.NOTHING, null, null, this, this);
459465
}
@@ -646,7 +652,6 @@ AbstractRenderer[] createSplitAndOverflowRenderers(int childPos, int layoutStatu
646652
splitRenderer.childRenderers.add(childResult.getSplitRenderer());
647653
}
648654

649-
650655
replaceSplitRendererKidFloats(waitingFloatsSplitRenderers, splitRenderer);
651656
for (IRenderer renderer : splitRenderer.childRenderers) {
652657
renderer.setParent(splitRenderer);
@@ -1084,6 +1089,14 @@ public MinMaxWidth getMinMaxWidth() {
10841089
return minMaxWidth;
10851090
}
10861091

1092+
void handleForcedPlacement(boolean anythingPlaced) {
1093+
// We placed something meaning that we don't need this property anymore while processing other children
1094+
// to do not force place them
1095+
if (anythingPlaced && hasOwnProperty(Property.FORCED_PLACEMENT)) {
1096+
deleteOwnProperty(Property.FORCED_PLACEMENT);
1097+
}
1098+
}
1099+
10871100
private void replaceSplitRendererKidFloats(Map<Integer, IRenderer> waitingFloatsSplitRenderers, IRenderer splitRenderer) {
10881101
for (Map.Entry<Integer, IRenderer> waitingSplitRenderer : waitingFloatsSplitRenderers.entrySet()) {
10891102
if (waitingSplitRenderer.getValue() != null) {

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,12 @@ Rectangle recalculateLayoutBoxBeforeChildLayout(Rectangle layoutBox,
330330
return layoutBoxCopy;
331331
}
332332

333+
@Override
334+
void handleForcedPlacement(boolean anythingPlaced) {
335+
// In (horizontal) FlexContainerRenderer Property.FORCED_PLACEMENT is still valid for other children
336+
// so do nothing
337+
}
338+
333339
void setHypotheticalCrossSize(Float mainSize, Float hypotheticalCrossSize) {
334340
hypotheticalCrossSizes.put(mainSize.floatValue(), hypotheticalCrossSize);
335341
}

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,13 +127,15 @@ public static Float retrieveRotatedLayoutWidth(float availableWidth, AbstractRen
127127
backup.<UnitValue>storeProperty(Property.HEIGHT);
128128
backup.<UnitValue>storeProperty(Property.MIN_HEIGHT);
129129
backup.<UnitValue>storeProperty(Property.MAX_HEIGHT);
130+
backup.storeBoolProperty(Property.FORCED_PLACEMENT);
130131
MinMaxWidth minMaxWidth = renderer.getMinMaxWidth();
131132
//Using this width for initial layout helps in case of small elements. They may have more free spaces but it's more likely they fit.
132133
float length = (minMaxWidth.getMaxWidth() + minMaxWidth.getMinWidth()) / 2 + MinMaxWidthUtils.getEps();
133134
LayoutResult layoutResult = renderer.layout(new LayoutContext(new LayoutArea(1, new Rectangle(length, AbstractRenderer.INF))));
134135
backup.restoreProperty(Property.HEIGHT);
135136
backup.restoreProperty(Property.MIN_HEIGHT);
136137
backup.restoreProperty(Property.MAX_HEIGHT);
138+
backup.restoreProperty(Property.FORCED_PLACEMENT);
137139

138140
Rectangle additions = new Rectangle(0, 0);
139141
renderer.applyPaddings(additions, true);
@@ -188,6 +190,15 @@ public Float storeFloatProperty(int property) {
188190
return value;
189191
}
190192

193+
public Boolean storeBoolProperty(int property) {
194+
Boolean value = renderer.getPropertyAsBoolean(property);
195+
if (value != null) {
196+
propertiesBackup.put(property, new PropertyBackup(value, renderer.hasOwnProperty(property)));
197+
renderer.setProperty(property, null);
198+
}
199+
return value;
200+
}
201+
191202
public <T> T storeProperty(int property) {
192203
T value = renderer.<T>getProperty(property);
193204
if (value != null) {

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

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1267,7 +1267,6 @@ public void floatsOnPageSplit06_03() throws IOException, InterruptedException {
12671267
div.add(img);
12681268
div.add(new Paragraph("some small text"));
12691269

1270-
// TODO DEVSIX-1655: blocks don't extend their height to MIN_HEIGHT if forced placement is applied, why?
12711270
document.add(div);
12721271

12731272
document.close();
@@ -1333,7 +1332,7 @@ public void floatsOnPageSplit08_01() throws IOException, InterruptedException {
13331332
}
13341333

13351334
@Test
1336-
@LogMessages(messages = @LogMessage(messageTemplate = LayoutLogMessageConstant.ELEMENT_DOES_NOT_FIT_AREA))
1335+
@LogMessages(messages = @LogMessage(messageTemplate = LayoutLogMessageConstant.ELEMENT_DOES_NOT_FIT_AREA, count = 2))
13371336
public void floatsOnPageSplit08_02() throws IOException, InterruptedException {
13381337
String cmpFileName = sourceFolder + "cmp_floatsOnPageSplit08_02.pdf";
13391338
String outFile = destinationFolder + "floatsOnPageSplit08_02.pdf";
@@ -1358,10 +1357,6 @@ public void floatsOnPageSplit08_02() throws IOException, InterruptedException {
13581357
document.add(containerDiv);
13591358
document.close();
13601359

1361-
// TODO DEVSIX-1655: currently forced placement is applied on containerDiv, which results in all it's content
1362-
// being forced placed at once, rather than content being split more gracefully (it makes sense to put the second
1363-
// image on the next empty area, not on current area).
1364-
13651360
Assert.assertNull(new CompareTool().compareByContent(outFile, cmpFileName, destinationFolder, "diff28_02_"));
13661361
}
13671362

@@ -1382,14 +1377,12 @@ public void floatsOnPageSplit08_03() throws IOException, InterruptedException {
13821377

13831378
// Adding normal image that will not fit on the first page and requires forced placement.
13841379
containerDiv.add(img);
1385-
// Adding more text that is naturally expected to be correctly shown.
1380+
// Adding more text that is naturally expected to be correctly shown.
13861381
containerDiv.add(new Paragraph(text));
13871382

13881383
document.add(containerDiv);
13891384
document.close();
13901385

1391-
// TODO DEVSIX-1655: text in the container div gets lost. And floating property doesn't actually affect this.
1392-
13931386
Assert.assertNull(new CompareTool().compareByContent(outFile, cmpFileName, destinationFolder, "diff28_03_"));
13941387
}
13951388

@@ -1476,8 +1469,6 @@ public void floatsOnPageSplit11() throws IOException, InterruptedException {
14761469
document.add(containerDiv);
14771470
document.close();
14781471

1479-
// TODO DEVSIX-1655: Forced placement is applied to the parent element, forcing it to return FULL even though part of the child element overflowed.
1480-
14811472
Assert.assertNull(new CompareTool().compareByContent(outFile, cmpFileName, destinationFolder, "diff31_"));
14821473
}
14831474

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,7 @@ public void imageTest07() throws IOException, InterruptedException {
278278

279279
@Test
280280
@LogMessages(messages = {
281-
@LogMessage(messageTemplate = LayoutLogMessageConstant.ELEMENT_DOES_NOT_FIT_AREA)
281+
@LogMessage(messageTemplate = LayoutLogMessageConstant.ELEMENT_DOES_NOT_FIT_AREA, count = 2)
282282
})
283283
public void imageTest08() throws IOException, InterruptedException {
284284
String outFileName = destinationFolder + "imageTest08.pdf";
Binary file not shown.
Binary file not shown.

0 commit comments

Comments
 (0)