Skip to content

Commit ec27580

Browse files
Merge branch 'float_splitting' into develop
2 parents a2e3ceb + f430c0d commit ec27580

20 files changed

+771
-108
lines changed

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

Lines changed: 162 additions & 92 deletions
Large diffs are not rendered by default.

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

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,22 @@ static boolean isRendererFloating(IRenderer renderer, FloatPropertyValue kidFloa
314314
return notAbsolutePos && kidFloatPropertyVal != null && !kidFloatPropertyVal.equals(FloatPropertyValue.NONE);
315315
}
316316

317+
static boolean isClearanceApplied(List<IRenderer> floatingRenderers, ClearPropertyValue clearPropertyValue) {
318+
if (clearPropertyValue == null || clearPropertyValue.equals(ClearPropertyValue.NONE)) {
319+
return false;
320+
}
321+
for (IRenderer floatingRenderer : floatingRenderers) {
322+
FloatPropertyValue floatPropertyValue = floatingRenderer.<FloatPropertyValue>getProperty(Property.FLOAT);
323+
324+
if (clearPropertyValue.equals(ClearPropertyValue.BOTH)
325+
|| (floatPropertyValue.equals(FloatPropertyValue.LEFT) && clearPropertyValue.equals(ClearPropertyValue.LEFT))
326+
|| (floatPropertyValue.equals(FloatPropertyValue.RIGHT) && clearPropertyValue.equals(ClearPropertyValue.RIGHT))) {
327+
return true;
328+
}
329+
}
330+
return false;
331+
}
332+
317333
private static void adjustBoxForFloatRight(Rectangle layoutBox, float blockWidth) {
318334
layoutBox.setX(layoutBox.getRight() - blockWidth);
319335
layoutBox.setWidth(blockWidth);

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,7 @@ public LayoutResult layout(LayoutContext layoutContext) {
221221
if (Boolean.TRUE.equals(getPropertyAsBoolean(Property.FORCED_PLACEMENT)) || (width > layoutBox.getWidth() && processOverflowX) || (height > layoutBox.getHeight() && processOverflowY)) {
222222
isPlacingForced = true;
223223
} else {
224+
occupiedArea.getBBox().setHeight(initialOccupiedAreaBBox.getHeight());
224225
return new MinMaxWidthLayoutResult(LayoutResult.NOTHING, occupiedArea, null, this, this);
225226
}
226227
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -442,7 +442,7 @@ public LineLayoutResult layout(LayoutContext layoutContext) {
442442
if (anythingPlaced || floatsPlaced) {
443443
result = new LineLayoutResult(LayoutResult.PARTIAL, occupiedArea, split[0], split[1], causeOfNothing);
444444
} else {
445-
result = new LineLayoutResult(LayoutResult.NOTHING, null, split[0], split[1], causeOfNothing);
445+
result = new LineLayoutResult(LayoutResult.NOTHING, null, split[0], split[1], null);
446446
}
447447
}
448448
if (newLineOccurred) {

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

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,11 @@ This file is part of the iText (R) project.
5050
import com.itextpdf.layout.layout.*;
5151
import com.itextpdf.layout.margincollapse.MarginsCollapseHandler;
5252
import com.itextpdf.layout.minmaxwidth.MinMaxWidth;
53-
import com.itextpdf.layout.property.*;
53+
import com.itextpdf.layout.property.FloatPropertyValue;
54+
import com.itextpdf.layout.property.Leading;
55+
import com.itextpdf.layout.property.OverflowPropertyValue;
56+
import com.itextpdf.layout.property.Property;
57+
import com.itextpdf.layout.property.TextAlignment;
5458
import org.slf4j.Logger;
5559
import org.slf4j.LoggerFactory;
5660

@@ -176,7 +180,6 @@ public LayoutResult layout(LayoutContext layoutContext) {
176180
float lineIndent = anythingPlaced ? 0 : (float) this.getPropertyAsFloat(Property.FIRST_LINE_INDENT);
177181
float childBBoxWidth = layoutBox.getWidth() - lineIndent;
178182
Rectangle childLayoutBox = new Rectangle(layoutBox.getX() + lineIndent, layoutBox.getY(), childBBoxWidth, layoutBox.getHeight());
179-
180183
currentRenderer.setProperty(Property.OVERFLOW_X, overflowX);
181184
currentRenderer.setProperty(Property.OVERFLOW_Y, overflowY);
182185
LineLayoutResult result = ((LineRenderer) currentRenderer.setParent(this)).layout(new LayoutContext(

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

Lines changed: 45 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ This file is part of the iText (R) project.
4444
package com.itextpdf.layout.renderer;
4545

4646
import com.itextpdf.io.LogMessageConstant;
47+
import com.itextpdf.io.util.MessageFormatUtil;
4748
import com.itextpdf.kernel.geom.Rectangle;
4849
import com.itextpdf.layout.layout.LayoutArea;
4950
import com.itextpdf.layout.layout.LayoutContext;
@@ -57,7 +58,6 @@ This file is part of the iText (R) project.
5758
import org.slf4j.Logger;
5859
import org.slf4j.LoggerFactory;
5960

60-
import com.itextpdf.io.util.MessageFormatUtil;
6161
import java.util.ArrayList;
6262
import java.util.List;
6363

@@ -72,6 +72,7 @@ public abstract class RootRenderer extends AbstractRenderer {
7272
private MarginsCollapseHandler marginsCollapseHandler;
7373
private LayoutArea initialCurrentArea;
7474
private List<Rectangle> floatRendererAreas;
75+
private List<IRenderer> waitingNextPageRenderers = new ArrayList<>();
7576

7677
public void addChild(IRenderer renderer) {
7778
// Some positioned renderers might have been fetched from non-positioned child and added to this renderer,
@@ -99,7 +100,7 @@ public void addChild(IRenderer renderer) {
99100
}
100101

101102
// Static layout
102-
for (int i = 0; currentArea != null && i < addedRenderers.size(); i++) {
103+
for (int i = 0; currentArea != null && i < addedRenderers.size(); i++) {
103104
renderer = addedRenderers.get(i);
104105

105106
processWaitingKeepWithNextElement(renderer);
@@ -113,11 +114,15 @@ public void addChild(IRenderer renderer) {
113114
if (marginsCollapsingEnabled && currentArea != null && renderer != null) {
114115
childMarginsInfo = marginsCollapseHandler.startChildMarginsHandling(renderer, currentArea.getBBox());
115116
}
117+
boolean rendererIsFloat = FloatingHelper.isRendererFloating(renderer);
116118
while (currentArea != null && renderer != null && (result = renderer.setParent(this).layout(
117119
new LayoutContext(currentArea.clone(), childMarginsInfo, floatRendererAreas)))
118120
.getStatus() != LayoutResult.FULL) {
119121
if (result.getStatus() == LayoutResult.PARTIAL) {
120-
if (result.getOverflowRenderer() instanceof ImageRenderer) {
122+
if (rendererIsFloat) {
123+
waitingNextPageRenderers.add(result.getOverflowRenderer());
124+
break;
125+
} else if (result.getOverflowRenderer() instanceof ImageRenderer) {
121126
((ImageRenderer) result.getOverflowRenderer()).autoScale(currentArea);
122127
} else {
123128
processRenderer(result.getSplitRenderer(), resultRenderers);
@@ -131,13 +136,18 @@ public void addChild(IRenderer renderer) {
131136
}
132137
} else if (result.getStatus() == LayoutResult.NOTHING) {
133138
if (result.getOverflowRenderer() instanceof ImageRenderer) {
134-
if (currentArea.getBBox().getHeight() < ((ImageRenderer) result.getOverflowRenderer()).imageHeight && !currentArea.isEmptyArea()) {
139+
if (currentArea.getBBox().getHeight() < ((ImageRenderer) result.getOverflowRenderer()).getOccupiedArea().getBBox().getHeight() && !currentArea.isEmptyArea()) {
140+
if (rendererIsFloat) {
141+
waitingNextPageRenderers.add(result.getOverflowRenderer());
142+
break;
143+
}
135144
updateCurrentAndInitialArea(result);
145+
} else {
146+
((ImageRenderer) result.getOverflowRenderer()).autoScale(currentArea);
147+
result.getOverflowRenderer().setProperty(Property.FORCED_PLACEMENT, true);
148+
Logger logger = LoggerFactory.getLogger(RootRenderer.class);
149+
logger.warn(MessageFormatUtil.format(LogMessageConstant.ELEMENT_DOES_NOT_FIT_AREA, ""));
136150
}
137-
((ImageRenderer)result.getOverflowRenderer()).autoScale(currentArea);
138-
result.getOverflowRenderer().setProperty(Property.FORCED_PLACEMENT, true);
139-
Logger logger = LoggerFactory.getLogger(RootRenderer.class);
140-
logger.warn(MessageFormatUtil.format(LogMessageConstant.ELEMENT_DOES_NOT_FIT_AREA, ""));
141151
} else {
142152
if (currentArea.isEmptyArea() && result.getAreaBreak() == null) {
143153
if (Boolean.TRUE.equals(result.getOverflowRenderer().getModelElement().<Boolean>getProperty(Property.KEEP_TOGETHER))) {
@@ -172,11 +182,16 @@ public void addChild(IRenderer renderer) {
172182
currentPageNumber = nextStoredArea.getPageNumber();
173183
nextStoredArea = null;
174184
} else {
185+
if (rendererIsFloat) {
186+
waitingNextPageRenderers.add(result.getOverflowRenderer());
187+
break;
188+
}
175189
updateCurrentAndInitialArea(result);
176190
}
177191
}
178192
}
179193
}
194+
180195
renderer = result.getOverflowRenderer();
181196

182197
if (marginsCollapsingEnabled) {
@@ -260,6 +275,7 @@ public void flush() {
260275
* and when no consequent element has been added. This method addresses such situations.
261276
*/
262277
public void close() {
278+
addAllWaitingNextPageRenderers();
263279
if (keepWithNextHangingRenderer != null) {
264280
keepWithNextHangingRenderer.setProperty(Property.KEEP_WITH_NEXT, false);
265281
IRenderer rendererToBeAdded = keepWithNextHangingRenderer;
@@ -303,7 +319,7 @@ protected void shrinkCurrentAreaAndProcessRenderer(IRenderer renderer, List<IRen
303319
if (currentArea != null) {
304320
float resultRendererHeight = result.getOccupiedArea().getBBox().getHeight();
305321
currentArea.getBBox().setHeight(currentArea.getBBox().getHeight() - resultRendererHeight);
306-
if (currentArea.isEmptyArea() && resultRendererHeight > 0) {
322+
if (currentArea.isEmptyArea() && (resultRendererHeight > 0 || FloatingHelper.isRendererFloating(renderer))) {
307323
currentArea.setEmptyArea(false);
308324
}
309325
processRenderer(renderer, resultRenderers);
@@ -402,5 +418,25 @@ private void updateCurrentAndInitialArea(LayoutResult overflowResult) {
402418
floatRendererAreas = new ArrayList<>();
403419
updateCurrentArea(overflowResult);
404420
initialCurrentArea = currentArea == null ? null : currentArea.clone();
421+
// TODO how bout currentArea == null ?
422+
addWaitingNextPageRenderers();
423+
}
424+
425+
private void addAllWaitingNextPageRenderers() {
426+
boolean marginsCollapsingEnabled = Boolean.TRUE.equals(getPropertyAsBoolean(Property.COLLAPSING_MARGINS));
427+
while (!waitingNextPageRenderers.isEmpty()) {
428+
if (marginsCollapsingEnabled) {
429+
marginsCollapseHandler = new MarginsCollapseHandler(this, null);
430+
}
431+
updateCurrentAndInitialArea(null);
432+
}
433+
}
434+
435+
private void addWaitingNextPageRenderers() {
436+
List<IRenderer> waitingFloatRenderers = new ArrayList<>(waitingNextPageRenderers);
437+
waitingNextPageRenderers.clear();
438+
for (IRenderer renderer : waitingFloatRenderers) {
439+
addChild(renderer);
440+
}
405441
}
406442
}

0 commit comments

Comments
 (0)