@@ -23,11 +23,13 @@ This file is part of the iText (R) project.
23
23
package com .itextpdf .layout .renderer ;
24
24
25
25
import com .itextpdf .kernel .geom .Rectangle ;
26
+ import com .itextpdf .layout .borders .Border ;
26
27
import com .itextpdf .layout .element .MulticolContainer ;
27
28
import com .itextpdf .layout .layout .LayoutArea ;
28
29
import com .itextpdf .layout .layout .LayoutContext ;
29
30
import com .itextpdf .layout .layout .LayoutResult ;
30
31
import com .itextpdf .layout .properties .Property ;
32
+ import com .itextpdf .layout .properties .UnitValue ;
31
33
32
34
import java .util .ArrayList ;
33
35
import java .util .List ;
@@ -38,7 +40,7 @@ This file is part of the iText (R) project.
38
40
public class MulticolRenderer extends AbstractRenderer {
39
41
40
42
private static final int MAX_RELAYOUT_COUNT = 4 ;
41
- private static final float ZERO_DELTA = 0.0001f ;
43
+ private static final float ZERO_DELTA = 0.0001F ;
42
44
43
45
private BlockRenderer elementRenderer ;
44
46
private int columnCount ;
@@ -54,22 +56,19 @@ public MulticolRenderer(MulticolContainer modelElement) {
54
56
super (modelElement );
55
57
}
56
58
57
- @ Override
58
- public IRenderer getNextRenderer () {
59
- logWarningIfGetNextRendererNotOverridden (MulticolRenderer .class , this .getClass ());
60
- return new MulticolRenderer ((MulticolContainer ) modelElement );
61
- }
62
-
63
59
/**
64
60
* {@inheritDoc}
65
61
*/
66
62
@ Override
67
63
public LayoutResult layout (LayoutContext layoutContext ) {
68
- ((MulticolContainer ) this .getModelElement ()).copyAllPropertiesToChildren ();
69
64
this .setProperty (Property .TREAT_AS_CONTINUOUS_CONTAINER , Boolean .TRUE );
70
- final Rectangle initialBBox = layoutContext .getArea ().getBBox ();
65
+ final Rectangle actualBBox = layoutContext .getArea ().getBBox ().clone ();
66
+ applyPaddings (actualBBox , false );
67
+ applyBorderBox (actualBBox , false );
68
+ applyMargins (actualBBox , false );
69
+
71
70
columnCount = (int ) this .<Integer >getProperty (Property .COLUMN_COUNT );
72
- columnWidth = initialBBox .getWidth () / columnCount ;
71
+ columnWidth = actualBBox .getWidth () / columnCount ;
73
72
if (this .elementRenderer == null ) {
74
73
// initialize elementRenderer on first layout when first child represents renderer of element which
75
74
// should be layouted in multicol, because on the next layouts this can have multiple children
@@ -85,7 +84,7 @@ public LayoutResult layout(LayoutContext layoutContext) {
85
84
86
85
approximateHeight = prelayoutResult .getOccupiedArea ().getBBox ().getHeight () / columnCount ;
87
86
88
- List <IRenderer > container = balanceContentAndLayoutColumns (layoutContext );
87
+ List <IRenderer > container = balanceContentAndLayoutColumns (layoutContext , actualBBox );
89
88
90
89
this .occupiedArea = calculateContainerOccupiedArea (layoutContext );
91
90
this .setChildRenderers (container );
@@ -97,19 +96,38 @@ public LayoutResult layout(LayoutContext layoutContext) {
97
96
return result ;
98
97
}
99
98
100
- private List <IRenderer > balanceContentAndLayoutColumns (LayoutContext prelayoutContext ) {
99
+ @ Override
100
+ public IRenderer getNextRenderer () {
101
+ logWarningIfGetNextRendererNotOverridden (MulticolRenderer .class , this .getClass ());
102
+ return new MulticolRenderer ((MulticolContainer ) modelElement );
103
+ }
104
+
105
+ private float safelyRetrieveFloatProperty (int property ) {
106
+ final Object value = this .<Object >getProperty (property );
107
+ if (value instanceof UnitValue ) {
108
+ return ((UnitValue ) value ).getValue ();
109
+ }
110
+ if (value instanceof Border ) {
111
+ return ((Border ) value ).getWidth ();
112
+ }
113
+ return 0F ;
114
+ }
115
+
116
+ private List <IRenderer > balanceContentAndLayoutColumns (LayoutContext prelayoutContext , Rectangle actualBBox ) {
101
117
Float additionalHeightPerIteration = null ;
102
- List <IRenderer > container = new ArrayList <>();
118
+ final List <IRenderer > container = new ArrayList <>();
103
119
int counter = MAX_RELAYOUT_COUNT ;
104
120
while (counter -- > 0 ) {
105
- IRenderer overflowRenderer = layoutColumnsAndReturnOverflowRenderer (prelayoutContext , container );
121
+ final IRenderer overflowRenderer = layoutColumnsAndReturnOverflowRenderer (prelayoutContext , container ,
122
+ actualBBox );
106
123
if (overflowRenderer == null ) {
107
124
return container ;
108
125
}
109
126
if (additionalHeightPerIteration == null ) {
110
127
LayoutResult overflowResult = overflowRenderer .layout (
111
128
new LayoutContext (new LayoutArea (1 , new Rectangle (columnWidth , INF ))));
112
- additionalHeightPerIteration = overflowResult .getOccupiedArea ().getBBox ().getHeight () / MAX_RELAYOUT_COUNT ;
129
+ additionalHeightPerIteration =
130
+ overflowResult .getOccupiedArea ().getBBox ().getHeight () / MAX_RELAYOUT_COUNT ;
113
131
}
114
132
if (Math .abs (additionalHeightPerIteration .floatValue ()) <= ZERO_DELTA ) {
115
133
return container ;
@@ -119,10 +137,22 @@ private List<IRenderer> balanceContentAndLayoutColumns(LayoutContext prelayoutCo
119
137
return container ;
120
138
}
121
139
140
+
122
141
private LayoutArea calculateContainerOccupiedArea (LayoutContext layoutContext ) {
123
142
LayoutArea area = layoutContext .getArea ().clone ();
124
- area .getBBox ().setHeight (approximateHeight );
125
- Rectangle initialBBox = layoutContext .getArea ().getBBox ();
143
+ float totalHeight = approximateHeight ;
144
+
145
+ totalHeight += safelyRetrieveFloatProperty (Property .PADDING_BOTTOM );
146
+ totalHeight += safelyRetrieveFloatProperty (Property .PADDING_TOP );
147
+ totalHeight += safelyRetrieveFloatProperty (Property .MARGIN_BOTTOM );
148
+ totalHeight += safelyRetrieveFloatProperty (Property .MARGIN_TOP );
149
+ totalHeight += safelyRetrieveFloatProperty (Property .BORDER_BOTTOM );
150
+ totalHeight += safelyRetrieveFloatProperty (Property .BORDER_TOP );
151
+ final float TOP_AND_BOTTOM = 2 ;
152
+ totalHeight += safelyRetrieveFloatProperty (Property .BORDER ) * TOP_AND_BOTTOM ;
153
+
154
+ area .getBBox ().setHeight (totalHeight );
155
+ final Rectangle initialBBox = layoutContext .getArea ().getBBox ();
126
156
area .getBBox ().setY (initialBBox .getY () + initialBBox .getHeight () - area .getBBox ().getHeight ());
127
157
return area ;
128
158
}
@@ -134,16 +164,20 @@ private BlockRenderer getElementsRenderer() {
134
164
return (BlockRenderer ) getChildRenderers ().get (0 );
135
165
}
136
166
137
- private IRenderer layoutColumnsAndReturnOverflowRenderer (LayoutContext preLayoutContext , List <IRenderer > container ) {
167
+ private IRenderer layoutColumnsAndReturnOverflowRenderer (LayoutContext preLayoutContext ,
168
+ List <IRenderer > container , Rectangle actualBBox ) {
138
169
container .clear ();
139
- Rectangle initialBBox = preLayoutContext .getArea ().getBBox ();
170
+
171
+ final Rectangle initialBBox = actualBBox .clone ();
140
172
IRenderer renderer = elementRenderer ;
141
173
for (int i = 0 ; i < columnCount && renderer != null ; i ++) {
142
174
LayoutArea tempArea = preLayoutContext .getArea ().clone ();
143
175
tempArea .getBBox ().setWidth (columnWidth );
144
176
tempArea .getBBox ().setHeight (approximateHeight );
145
177
tempArea .getBBox ().setX (initialBBox .getX () + columnWidth * i );
146
- tempArea .getBBox ().setY (initialBBox .getY () + initialBBox .getHeight () - tempArea .getBBox ().getHeight ());
178
+ tempArea .getBBox ().setY (initialBBox .getY () + initialBBox .getHeight () - tempArea .getBBox ()
179
+ .getHeight ());
180
+
147
181
LayoutContext columnContext = new LayoutContext (tempArea , preLayoutContext .getMarginsCollapseInfo (),
148
182
preLayoutContext .getFloatRendererAreas (), preLayoutContext .isClippedHeight ());
149
183
0 commit comments