Skip to content

Commit 57d9a67

Browse files
committed
Implement continuous container logic for MulticolRenderer
DEVSIX-7626
1 parent 1094128 commit 57d9a67

File tree

65 files changed

+67
-31
lines changed

Some content is hidden

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

65 files changed

+67
-31
lines changed

layout/src/main/java/com/itextpdf/layout/properties/ContinuousContainer.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ This file is part of the iText (R) project.
2525
import com.itextpdf.layout.IPropertyContainer;
2626
import com.itextpdf.layout.borders.Border;
2727
import com.itextpdf.layout.renderer.AbstractRenderer;
28-
import com.itextpdf.layout.renderer.BlockRenderer;
2928
import com.itextpdf.layout.renderer.IRenderer;
3029

3130
import java.util.HashMap;
@@ -106,7 +105,7 @@ private static void clearPropertiesFromSplitRenderer(AbstractRenderer blockRende
106105
*
107106
* @param blockRenderer the renderer that is used to reapply properties.
108107
*/
109-
public void reApplyProperties(BlockRenderer blockRenderer) {
108+
public void reApplyProperties(AbstractRenderer blockRenderer) {
110109
for (int property : PROPERTIES_NEEDED_FOR_CONTINUOUS_CONTAINER) {
111110
blockRenderer.setProperty(property, properties.get(property));
112111
}

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

Lines changed: 43 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ public class MulticolRenderer extends AbstractRenderer {
5555
private Float heightFromProperties;
5656
private float columnGap;
5757

58+
private boolean isFirstLayout = true;
59+
5860
/**
5961
* Creates a DivRenderer from its corresponding layout object.
6062
*
@@ -84,6 +86,8 @@ public LayoutResult layout(LayoutContext layoutContext) {
8486
Rectangle actualBBox = layoutContext.getArea().getBBox().clone();
8587
float originalWidth = actualBBox.getWidth();
8688
applyWidth(actualBBox, originalWidth);
89+
90+
ContinuousContainer.setupContinuousContainerIfNeeded(this);
8791
applyPaddings(actualBBox, false);
8892
applyBorderBox(actualBBox, false);
8993
applyMargins(actualBBox, false);
@@ -103,6 +107,12 @@ public LayoutResult layout(LayoutContext layoutContext) {
103107
if (layoutResult.getSplitRenderers().isEmpty()) {
104108
return new LayoutResult(LayoutResult.NOTHING, null, null, this, layoutResult.getCauseOfNothing());
105109
} else if (layoutResult.getOverflowRenderer() == null) {
110+
final ContinuousContainer continuousContainer = this.<ContinuousContainer>getProperty(
111+
Property.TREAT_AS_CONTINUOUS_CONTAINER_RESULT);
112+
if (continuousContainer != null) {
113+
continuousContainer.reApplyProperties(this);
114+
}
115+
106116
this.childRenderers.clear();
107117
addAllChildRenderers(layoutResult.getSplitRenderers());
108118
this.occupiedArea = calculateContainerOccupiedArea(layoutContext, true);
@@ -201,7 +211,8 @@ protected AbstractRenderer createSplitRenderer(List<IRenderer> children) {
201211
* @return a new {@link AbstractRenderer} instance
202212
*/
203213
protected AbstractRenderer createOverflowRenderer(IRenderer overflowedContentRenderer) {
204-
AbstractRenderer overflowRenderer = (AbstractRenderer) getNextRenderer();
214+
MulticolRenderer overflowRenderer = (MulticolRenderer) getNextRenderer();
215+
overflowRenderer.isFirstLayout = false;
205216
overflowRenderer.parent = parent;
206217
overflowRenderer.modelElement = modelElement;
207218
overflowRenderer.addAllProperties(getOwnProperties());
@@ -260,9 +271,10 @@ private Float determineHeight(Rectangle parentBBox) {
260271
}
261272

262273

263-
private void recalculateHeightWidthAfterLayouting(Rectangle parentBBox) {
274+
private void recalculateHeightWidthAfterLayouting(Rectangle parentBBox, boolean isFull) {
264275
Float height = determineHeight(parentBBox);
265276
if (height != null) {
277+
height = updateOccupiedHeight((float) height, isFull);
266278
float heightDelta = parentBBox.getHeight() - (float) height;
267279
parentBBox.moveUp(heightDelta);
268280
parentBBox.setHeight((float) height);
@@ -298,13 +310,6 @@ private MulticolLayoutResult balanceContentAndLayoutColumns(LayoutContext prelay
298310
float workingHeight = approximateHeight;
299311
if (heightFromProperties != null) {
300312
workingHeight = Math.min((float) heightFromProperties, (float) approximateHeight);
301-
workingHeight -= safelyRetrieveFloatProperty(Property.PADDING_TOP);
302-
workingHeight -= safelyRetrieveFloatProperty(Property.PADDING_BOTTOM);
303-
workingHeight -= safelyRetrieveFloatProperty(Property.BORDER_TOP);
304-
workingHeight -= safelyRetrieveFloatProperty(Property.BORDER_BOTTOM);
305-
workingHeight -= safelyRetrieveFloatProperty(Property.BORDER) * 2;
306-
workingHeight -= safelyRetrieveFloatProperty(Property.MARGIN_TOP);
307-
workingHeight -= safelyRetrieveFloatProperty(Property.MARGIN_BOTTOM);
308313
}
309314
result = layoutColumnsAndReturnOverflowRenderer(prelayoutContext, actualBbox, workingHeight);
310315

@@ -371,29 +376,43 @@ private void clearOverFlowRendererIfNeeded(MulticolLayoutResult result) {
371376

372377
private LayoutArea calculateContainerOccupiedArea(LayoutContext layoutContext, boolean isFull) {
373378
LayoutArea area = layoutContext.getArea().clone();
374-
float totalHeight = approximateHeight;
375-
376-
if (isFull) {
377-
totalHeight += safelyRetrieveFloatProperty(Property.PADDING_BOTTOM);
378-
totalHeight += safelyRetrieveFloatProperty(Property.MARGIN_BOTTOM);
379-
totalHeight += safelyRetrieveFloatProperty(Property.BORDER_BOTTOM);
380-
}
381-
totalHeight += safelyRetrieveFloatProperty(Property.PADDING_TOP);
382-
383-
totalHeight += safelyRetrieveFloatProperty(Property.MARGIN_TOP);
384379

385-
totalHeight += safelyRetrieveFloatProperty(Property.BORDER_TOP);
386-
final float TOP_AND_BOTTOM = isFull ? 2 : 1;
387-
388-
totalHeight += safelyRetrieveFloatProperty(Property.BORDER) * TOP_AND_BOTTOM;
380+
final float totalHeight = updateOccupiedHeight(approximateHeight, isFull);
389381

390382
area.getBBox().setHeight(totalHeight);
391383
final Rectangle initialBBox = layoutContext.getArea().getBBox();
392384
area.getBBox().setY(initialBBox.getY() + initialBBox.getHeight() - area.getBBox().getHeight());
393-
recalculateHeightWidthAfterLayouting(area.getBBox());
385+
recalculateHeightWidthAfterLayouting(area.getBBox(), isFull);
394386
return area;
395387
}
396388

389+
private float updateOccupiedHeight(float initialHeight, boolean isFull) {
390+
if (isFull) {
391+
initialHeight += safelyRetrieveFloatProperty(Property.PADDING_BOTTOM);
392+
initialHeight += safelyRetrieveFloatProperty(Property.MARGIN_BOTTOM);
393+
if (!this.hasOwnProperty(Property.BORDER) || this.<Border>getProperty(Property.BORDER) == null) {
394+
initialHeight += safelyRetrieveFloatProperty(Property.BORDER_BOTTOM);
395+
}
396+
}
397+
initialHeight += safelyRetrieveFloatProperty(Property.PADDING_TOP);
398+
399+
initialHeight += safelyRetrieveFloatProperty(Property.MARGIN_TOP);
400+
401+
if (!this.hasOwnProperty(Property.BORDER) || this.<Border>getProperty(Property.BORDER) == null) {
402+
initialHeight += safelyRetrieveFloatProperty(Property.BORDER_TOP);
403+
}
404+
405+
// isFirstLayout is necessary to handle the case when multicol container layouted in more
406+
// than 2 pages, and on the last page layout result is full, but there is no bottom border
407+
float TOP_AND_BOTTOM = isFull && isFirstLayout ? 2 : 1;
408+
// Multicol container layouted in more than 3 pages, and there is a page where there are no bottom and top borders
409+
if (!isFull && !isFirstLayout) {
410+
TOP_AND_BOTTOM = 0;
411+
}
412+
initialHeight += safelyRetrieveFloatProperty(Property.BORDER) * TOP_AND_BOTTOM;
413+
return initialHeight;
414+
}
415+
397416
private BlockRenderer getElementsRenderer() {
398417
if (!(getChildRenderers().size() == 1 && getChildRenderers().get(0) instanceof BlockRenderer)) {
399418
throw new IllegalStateException("Invalid child renderers, it should be one and be a block element");

layout/src/test/java/com/itextpdf/layout/element/MulticolContainerTest.java

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,6 @@ public void continuousColumContainerParagraphAllChildEnd() throws IOException, I
209209
});
210210
}
211211

212-
//TODO: DEVSIX-7626
213212
@Test
214213
public void continuousColumContainerParagraphOverflowShouldShow() throws IOException, InterruptedException {
215214
executeTest("continuousColumContainerParagraphOverflowShouldShow", ctx -> {
@@ -224,7 +223,6 @@ public void continuousColumContainerParagraphOverflowShouldShow() throws IOExcep
224223
});
225224
}
226225

227-
//TODO: DEVSIX-7626
228226
@Test
229227
public void extraLargeColumnParagraphTest() throws IOException, InterruptedException {
230228
executeTest("extraLargeColumnParagraphTest", ctx -> {
@@ -239,7 +237,6 @@ public void extraLargeColumnParagraphTest() throws IOException, InterruptedExcep
239237
});
240238
}
241239

242-
//TODO: DEVSIX-7626
243240
@Test
244241
public void largeColumnParagraphWithMarginTest() throws IOException, InterruptedException {
245242
executeTest("largeColumnParagraphWithMarginTest", ctx -> {
@@ -251,7 +248,6 @@ public void largeColumnParagraphWithMarginTest() throws IOException, Interrupted
251248
});
252249
}
253250

254-
//TODO: DEVSIX-7626
255251
@Test
256252
public void largeColumnParagraphWithPaddingTest() throws IOException, InterruptedException {
257253
executeTest("largeColumnParagraphWithPaddingTest", ctx -> {
@@ -263,7 +259,6 @@ public void largeColumnParagraphWithPaddingTest() throws IOException, Interrupte
263259
});
264260
}
265261

266-
//TODO: DEVSIX-7626
267262
@Test
268263
public void largeColumnParagraphWithBorderTest() throws IOException, InterruptedException {
269264
executeTest("largeColumnParagraphWithBorderTest", ctx -> {
@@ -856,6 +851,7 @@ public void heightPaddingTest() throws IOException, InterruptedException {
856851
public void heightMarginTest() throws IOException, InterruptedException {
857852
executeTest("heightMarginTest", ctx -> {
858853
ctx.setProperty(Property.COLUMN_COUNT, 3);
854+
859855
//content should be clipped
860856
ctx.setHeight(200);
861857
ctx.setBackgroundColor(DEFAULT_BACKGROUND_COLOR);

0 commit comments

Comments
 (0)