@@ -76,7 +76,9 @@ This file is part of the iText (R) project.
76
76
import java .util .ArrayList ;
77
77
import java .util .Collections ;
78
78
import java .util .HashMap ;
79
+ import java .util .LinkedHashMap ;
79
80
import java .util .List ;
81
+ import java .util .Map ;
80
82
81
83
public abstract class BlockRenderer extends AbstractRenderer {
82
84
@@ -87,8 +89,8 @@ protected BlockRenderer(IElement modelElement) {
87
89
@ Override
88
90
public LayoutResult layout (LayoutContext layoutContext ) {
89
91
overrideHeightProperties ();
92
+ Map <Integer , IRenderer > waitingFloatsSplitRenderers = new LinkedHashMap <>();
90
93
List <IRenderer > waitingOverflowFloatRenderers = new ArrayList <>();
91
- List <IRenderer > waitingSplitFloatRenderers = new ArrayList <>();
92
94
boolean wasHeightClipped = false ;
93
95
int pageNumber = layoutContext .getArea ().getPageNumber ();
94
96
@@ -166,19 +168,18 @@ public LayoutResult layout(LayoutContext layoutContext) {
166
168
// the first renderer (one of childRenderers or their children) to produce LayoutResult.NOTHING
167
169
IRenderer causeOfNothing = null ;
168
170
boolean anythingPlaced = false ;
169
- List <IRenderer > ignoredChildRenderers = new ArrayList <>();
170
171
for (int childPos = 0 ; childPos < childRenderers .size (); childPos ++) {
171
172
IRenderer childRenderer = childRenderers .get (childPos );
172
173
LayoutResult result ;
173
174
childRenderer .setParent (this );
174
175
MarginsCollapseInfo childMarginsInfo = null ;
175
- if (! waitingOverflowFloatRenderers . isEmpty () &&
176
- FloatingHelper . isFloatAffectedByClear ( waitingOverflowFloatRenderers . get ( waitingOverflowFloatRenderers . size () - 1 ).< FloatPropertyValue > getProperty ( Property . FLOAT ),
177
- childRenderer .<ClearPropertyValue >getProperty (Property .CLEAR ))) {
178
- return splitIfClearRendererIsPresentAfterFloatRendererWasSplitted (childPos , waitingSplitFloatRenderers ,
176
+
177
+ // TODO process correctly for floats with clear
178
+ if (! waitingOverflowFloatRenderers . isEmpty () && FloatingHelper . isClearanceApplied ( waitingOverflowFloatRenderers , childRenderer .<ClearPropertyValue >getProperty (Property .CLEAR ))) {
179
+ return splitIfClearRendererIsPresentAfterFloatRendererWasSplit (childPos , waitingFloatsSplitRenderers ,
179
180
waitingOverflowFloatRenderers , blockMaxHeight , wasHeightClipped , marginsCollapseHandler ,
180
181
layoutContext .getArea ().getBBox (), clearHeightCorrection , marginsCollapsingEnabled , isCellRenderer ,
181
- paddings , borders , layoutContext .getFloatRendererAreas (), causeOfNothing );
182
+ paddings , borders , layoutContext .getFloatRendererAreas (), causeOfNothing , layoutBox );
182
183
}
183
184
if (marginsCollapsingEnabled ) {
184
185
childMarginsInfo = marginsCollapseHandler .startChildMarginsHandling (childRenderer , layoutBox );
@@ -236,17 +237,15 @@ public LayoutResult layout(LayoutContext layoutContext) {
236
237
if (result .getStatus () == LayoutResult .PARTIAL ) {
237
238
if (currentAreaPos + 1 == areas .size ()) {
238
239
239
- AbstractRenderer [] splitAndOverflowRenderers = createSplitAndOverflowRenderers (childPos , ignoredChildRenderers ,
240
- result , childRenderer , floatRendererAreas , layoutContext .getArea ().getBBox (), clearHeightCorrection ,
241
- marginsCollapsingEnabled , waitingSplitFloatRenderers , waitingOverflowFloatRenderers , LayoutResult .PARTIAL );
242
- AbstractRenderer splitRenderer = splitAndOverflowRenderers [0 ];
243
- splitRenderer .childRenderers .add (result .getSplitRenderer ());
244
- FloatingHelper .adjustResultOccupiedAreaForFloatAndClear (childRenderer , floatRendererAreas , parentBBox , clearHeightCorrection , marginsCollapsingEnabled );
245
- if (splitAndOverflowRenderers .length == 1 ) {
246
- waitingSplitFloatRenderers = splitRenderer .childRenderers ;
240
+ AbstractRenderer [] splitAndOverflowRenderers = createSplitAndOverflowRenderers (childPos , waitingFloatsSplitRenderers ,
241
+ result , childRenderer , waitingOverflowFloatRenderers , LayoutResult .PARTIAL );
242
+ if (splitAndOverflowRenderers == null ) {
243
+ waitingFloatsSplitRenderers .put (childPos , result .getSplitRenderer ());
247
244
break ;
248
245
}
249
246
247
+ AbstractRenderer splitRenderer = splitAndOverflowRenderers [0 ];
248
+ splitRenderer .childRenderers .add (result .getSplitRenderer ());
250
249
AbstractRenderer overflowRenderer = splitAndOverflowRenderers [1 ];
251
250
overflowRenderer .deleteOwnProperty (Property .FORCED_PLACEMENT );
252
251
@@ -270,11 +269,11 @@ public LayoutResult layout(LayoutContext layoutContext) {
270
269
applyBorderBox (occupiedArea .getBBox (), borders , true );
271
270
applyMargins (occupiedArea .getBBox (), true );
272
271
272
+ LayoutArea editedArea = FloatingHelper .adjustResultOccupiedAreaForFloatAndClear (this , layoutContext .getFloatRendererAreas (), layoutContext .getArea ().getBBox (), clearHeightCorrection , marginsCollapsingEnabled );
273
273
if (wasHeightClipped ) {
274
- LayoutArea editedArea = FloatingHelper .adjustResultOccupiedAreaForFloatAndClear (this , layoutContext .getFloatRendererAreas (), layoutContext .getArea ().getBBox (), clearHeightCorrection , marginsCollapsingEnabled );
275
274
return new LayoutResult (LayoutResult .FULL , editedArea , splitRenderer , null );
276
275
} else {
277
- return new LayoutResult (LayoutResult .PARTIAL , occupiedArea , splitRenderer , overflowRenderer , causeOfNothing );
276
+ return new LayoutResult (LayoutResult .PARTIAL , editedArea , splitRenderer , overflowRenderer , causeOfNothing );
278
277
}
279
278
} else {
280
279
childRenderers .set (childPos , result .getSplitRenderer ());
@@ -286,16 +285,14 @@ public LayoutResult layout(LayoutContext layoutContext) {
286
285
boolean keepTogether = isKeepTogether ();
287
286
int layoutResult = anythingPlaced && !keepTogether ? LayoutResult .PARTIAL : LayoutResult .NOTHING ;
288
287
289
- AbstractRenderer [] splitAndOverflowRenderers = createSplitAndOverflowRenderers (childPos , ignoredChildRenderers ,
290
- result , childRenderer , floatRendererAreas , layoutContext .getArea ().getBBox (), clearHeightCorrection ,
291
- marginsCollapsingEnabled , waitingSplitFloatRenderers , waitingOverflowFloatRenderers , layoutResult );
288
+ AbstractRenderer [] splitAndOverflowRenderers = createSplitAndOverflowRenderers (childPos , waitingFloatsSplitRenderers ,
289
+ result , childRenderer , waitingOverflowFloatRenderers , layoutResult );
292
290
293
- AbstractRenderer splitRenderer = splitAndOverflowRenderers [0 ];
294
- waitingSplitFloatRenderers = splitRenderer .childRenderers ;
295
- if (splitAndOverflowRenderers .length == 1 ) {
296
- ignoredChildRenderers .add (childRenderer );
291
+ if (splitAndOverflowRenderers == null ) {
292
+ waitingFloatsSplitRenderers .put (childPos , null );
297
293
break ;
298
294
}
295
+ AbstractRenderer splitRenderer = splitAndOverflowRenderers [0 ];
299
296
AbstractRenderer overflowRenderer = splitAndOverflowRenderers [1 ];
300
297
301
298
if (isRelativePosition () && positionedRenderers .size () > 0 ) {
@@ -335,11 +332,14 @@ public LayoutResult layout(LayoutContext layoutContext) {
335
332
applyBorderBox (occupiedArea .getBBox (), borders , true );
336
333
applyMargins (occupiedArea .getBBox (), true );
337
334
335
+
338
336
if (Boolean .TRUE .equals (getPropertyAsBoolean (Property .FORCED_PLACEMENT )) || wasHeightClipped ) {
339
- return new LayoutResult (LayoutResult .FULL , occupiedArea , splitRenderer , null , null );
337
+ LayoutArea editedArea = FloatingHelper .adjustResultOccupiedAreaForFloatAndClear (this , layoutContext .getFloatRendererAreas (), layoutContext .getArea ().getBBox (), clearHeightCorrection , marginsCollapsingEnabled );
338
+ return new LayoutResult (LayoutResult .FULL , editedArea , splitRenderer , null , null );
340
339
} else {
341
340
if (layoutResult != LayoutResult .NOTHING ) {
342
- return new LayoutResult (layoutResult , occupiedArea , splitRenderer , overflowRenderer , null ).setAreaBreak (result .getAreaBreak ());
341
+ LayoutArea editedArea = FloatingHelper .adjustResultOccupiedAreaForFloatAndClear (this , layoutContext .getFloatRendererAreas (), layoutContext .getArea ().getBBox (), clearHeightCorrection , marginsCollapsingEnabled );
342
+ return new LayoutResult (layoutResult , editedArea , splitRenderer , overflowRenderer , null ).setAreaBreak (result .getAreaBreak ());
343
343
} else {
344
344
return new LayoutResult (layoutResult , null , null , overflowRenderer , result .getCauseOfNothing ()).setAreaBreak (result .getAreaBreak ());
345
345
}
@@ -357,7 +357,7 @@ public LayoutResult layout(LayoutContext layoutContext) {
357
357
if (marginsCollapsingEnabled ) {
358
358
marginsCollapseHandler .endChildMarginsHandling (layoutBox );
359
359
}
360
- if (result .getStatus () == LayoutResult .FULL && ( waitingOverflowFloatRenderers . isEmpty () || ! FloatingHelper . isRendererFloating ( childRenderer )) ) {
360
+ if (result .getStatus () == LayoutResult .FULL ) {
361
361
layoutBox .setHeight (result .getOccupiedArea ().getBBox ().getY () - layoutBox .getY ());
362
362
if (childRenderer .getOccupiedArea () != null ) {
363
363
// Use occupied area's bbox width so that for absolutely positioned renderers we do not align using full width
@@ -445,19 +445,35 @@ public LayoutResult layout(LayoutContext layoutContext) {
445
445
overflowRenderer = createOverflowRenderer (LayoutResult .PARTIAL );
446
446
overflowRenderer .getChildRenderers ().addAll (waitingOverflowFloatRenderers );
447
447
}
448
- IRenderer splitRenderer ;
449
- if (!waitingSplitFloatRenderers .isEmpty ()) {
448
+ AbstractRenderer splitRenderer = this ;
449
+ if (!waitingFloatsSplitRenderers .isEmpty ()) {
450
450
splitRenderer = createSplitRenderer (LayoutResult .PARTIAL );
451
- splitRenderer .getChildRenderers ().addAll (waitingSplitFloatRenderers );
452
- } else {
453
- splitRenderer = this ;
451
+ splitRenderer .childRenderers = new ArrayList <>(childRenderers );
452
+ replaceSplitRendererKidFloats (waitingFloatsSplitRenderers , splitRenderer );
454
453
}
455
454
456
- if ( null == overflowRenderer ) {
457
- LayoutArea editedArea = FloatingHelper . adjustResultOccupiedAreaForFloatAndClear ( this , layoutContext . getFloatRendererAreas (), layoutContext . getArea (). getBBox (), clearHeightCorrection , marginsCollapsingEnabled );
455
+ LayoutArea editedArea = FloatingHelper . adjustResultOccupiedAreaForFloatAndClear ( this , layoutContext . getFloatRendererAreas (), layoutContext . getArea (). getBBox (), clearHeightCorrection , marginsCollapsingEnabled );
456
+ if ( overflowRenderer == null ) {
458
457
return new LayoutResult (LayoutResult .FULL , editedArea , splitRenderer , null , causeOfNothing );
459
458
} else {
460
- return new LayoutResult (LayoutResult .PARTIAL , occupiedArea , splitRenderer , overflowRenderer , causeOfNothing );
459
+ // assert splitRenderer != this; // TODO review
460
+ return new LayoutResult (LayoutResult .PARTIAL , editedArea , splitRenderer , overflowRenderer , causeOfNothing );
461
+ }
462
+ }
463
+
464
+ private void replaceSplitRendererKidFloats (Map <Integer , IRenderer > waitingFloatsSplitRenderers , IRenderer splitRenderer ) {
465
+ for (Map .Entry <Integer , IRenderer > waitingSplitRenderer : waitingFloatsSplitRenderers .entrySet ()) {
466
+ if (waitingSplitRenderer .getValue () != null ) {
467
+ splitRenderer .getChildRenderers ().set (waitingSplitRenderer .getKey (), waitingSplitRenderer .getValue ());
468
+ } else {
469
+ // splitRenderer.getChildRenderers().remove((int)waitingSplitRenderer.getKey());
470
+ splitRenderer .getChildRenderers ().set ((int )waitingSplitRenderer .getKey (), null );
471
+ }
472
+ }
473
+ for (int i = splitRenderer .getChildRenderers ().size () - 1 ; i >= 0 ; --i ) {
474
+ if (splitRenderer .getChildRenderers ().get (i ) == null ) {
475
+ splitRenderer .getChildRenderers ().remove (i );
476
+ }
461
477
}
462
478
}
463
479
@@ -778,22 +794,29 @@ MinMaxWidth correctMinMaxWidth(MinMaxWidth minMaxWidth) {
778
794
return minMaxWidth ;
779
795
}
780
796
781
- private LayoutResult splitIfClearRendererIsPresentAfterFloatRendererWasSplitted (int childPos , List <IRenderer > waitingSplitRenderers ,
782
- List <IRenderer > waitingOverflowRenderers ,
783
- Float blockMaxHeight , boolean wasHeightClipped ,
784
- MarginsCollapseHandler marginsCollapseHandler ,
785
- Rectangle parentBBox , float clearHeightCorrection ,
786
- boolean marginsCollapsingEnabled , boolean isCellRenderer ,
787
- float [] paddings , Border [] borders ,
788
- List <Rectangle > floatRendererAreas , IRenderer causeOfNothing ) {
797
+ private LayoutResult splitIfClearRendererIsPresentAfterFloatRendererWasSplit (int childPos , Map <Integer , IRenderer > waitingFloatsSplitRenderers ,
798
+ List <IRenderer > waitingFloatsOverflowRenderers ,
799
+ Float blockMaxHeight , boolean wasHeightClipped ,
800
+ MarginsCollapseHandler marginsCollapseHandler ,
801
+ Rectangle parentBBox , float clearHeightCorrection ,
802
+ boolean marginsCollapsingEnabled , boolean isCellRenderer ,
803
+ float [] paddings , Border [] borders ,
804
+ List <Rectangle > floatRendererAreas , IRenderer causeOfNothing , Rectangle layoutBox ) {
805
+
806
+ if (marginsCollapsingEnabled && !isCellRenderer ) {
807
+ marginsCollapseHandler .endMarginsCollapse (layoutBox );
808
+ }
789
809
AbstractRenderer splitRenderer = createSplitRenderer (LayoutResult .PARTIAL );
810
+ Rectangle splitRendererOccupiedArea = splitRenderer .getOccupiedArea ().getBBox ();
811
+ splitRendererOccupiedArea .increaseHeight (splitRendererOccupiedArea .getY () - layoutBox .getY ()).setY (layoutBox .getY ());
790
812
splitRenderer .childRenderers = new ArrayList <>(childRenderers .subList (0 , childPos ));
791
- splitRenderer .childRenderers = waitingSplitRenderers ;
813
+
814
+ replaceSplitRendererKidFloats (waitingFloatsSplitRenderers , splitRenderer );
792
815
793
816
AbstractRenderer overflowRenderer = createOverflowRenderer (LayoutResult .PARTIAL );
794
817
// Apply forced placement only on split renderer
795
818
overflowRenderer .deleteOwnProperty (Property .FORCED_PLACEMENT );
796
- overflowRenderer .childRenderers .addAll (waitingOverflowRenderers );
819
+ overflowRenderer .childRenderers .addAll (waitingFloatsOverflowRenderers );
797
820
overflowRenderer .childRenderers .addAll (childRenderers .subList (childPos , childRenderers .size ()));
798
821
799
822
@@ -813,9 +836,6 @@ private LayoutResult splitIfClearRendererIsPresentAfterFloatRendererWasSplitted(
813
836
.moveDown ((float ) blockMaxHeight - occupiedArea .getBBox ().getHeight ())
814
837
.setHeight ((float ) blockMaxHeight );
815
838
}
816
- if (marginsCollapsingEnabled && !isCellRenderer ) {
817
- marginsCollapseHandler .endMarginsCollapse (occupiedArea .getBBox ());
818
- }
819
839
820
840
applyPaddings (occupiedArea .getBBox (), paddings , true );
821
841
applyBorderBox (occupiedArea .getBBox (), borders , true );
@@ -830,25 +850,20 @@ private LayoutResult splitIfClearRendererIsPresentAfterFloatRendererWasSplitted(
830
850
}
831
851
}
832
852
833
- private AbstractRenderer [] createSplitAndOverflowRenderers (int childPos , List <IRenderer > ignoredChildRenderers , LayoutResult result ,
834
- IRenderer childRenderer , List <Rectangle > floatRendererAreas , Rectangle parentBBox ,
835
- float clearHeightCorrection , boolean marginsCollapsingEnabled ,
836
- List <IRenderer > waitingSplitFloatRenderers , List <IRenderer > waitingOverflowFloatRenderers ,
853
+ private AbstractRenderer [] createSplitAndOverflowRenderers (int childPos , Map <Integer , IRenderer > waitingFloatsSplitRenderers , LayoutResult result ,
854
+ IRenderer childRenderer , List <IRenderer > waitingOverflowFloatRenderers ,
837
855
int layoutStatus ) {
838
856
AbstractRenderer splitRenderer = createSplitRenderer (layoutStatus );
839
857
splitRenderer .childRenderers = new ArrayList <>(childRenderers .subList (0 , childPos ));
840
858
841
- for (IRenderer ignoredRenderer : ignoredChildRenderers ) {
842
- splitRenderer .childRenderers .remove (ignoredRenderer );
843
- }
859
+ replaceSplitRendererKidFloats (waitingFloatsSplitRenderers , splitRenderer );
844
860
for (IRenderer renderer : splitRenderer .childRenderers ) {
845
861
renderer .setParent (splitRenderer );
846
862
}
847
863
848
864
if (FloatingHelper .isRendererFloating (childRenderer )) {
849
- // ignoredChildRenderers.add(childRenderer);
850
865
waitingOverflowFloatRenderers .add (result .getOverflowRenderer ());
851
- return new AbstractRenderer []{ splitRenderer } ;
866
+ return null ;
852
867
}
853
868
AbstractRenderer overflowRenderer = createOverflowRenderer (layoutStatus );
854
869
overflowRenderer .childRenderers .addAll (waitingOverflowFloatRenderers );
0 commit comments