Skip to content

Commit c24cac5

Browse files
yulian-gaponenkoitext-teamcity
authored andcommitted
Fixed critical issues with floats splitting that might lead to infinite loop, also some minor fixes
DEVSIX-1267 Autoported commit. Original commit hash: [f430c0de0]
1 parent c0a4f26 commit c24cac5

File tree

5 files changed

+100
-31
lines changed

5 files changed

+100
-31
lines changed

itext.tests/itext.layout.tests/itext/layout/FloatTest.cs

Lines changed: 57 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -663,9 +663,8 @@ public virtual void ClearanceApplyingPageSplit07() {
663663
/// <exception cref="System.IO.IOException"/>
664664
/// <exception cref="System.Exception"/>
665665
[NUnit.Framework.Test]
666+
[NUnit.Framework.Ignore("DEVSIX-1437")]
666667
public virtual void ClearanceApplyingPageSplit08() {
667-
// TODO process NOTHING case - only floats with nothing overflowed, clear is met
668-
// TODO avoid possible infinite loop in this case.
669668
String cmpFileName = sourceFolder + "cmp_clearanceApplyingPageSplit08.pdf";
670669
String outFile = destinationFolder + "clearanceApplyingPageSplit08.pdf";
671670
Document document = new Document(new PdfDocument(new PdfWriter(outFile)));
@@ -716,6 +715,7 @@ public virtual void ClearanceApplyingPageSplit09() {
716715
/// <exception cref="System.IO.IOException"/>
717716
/// <exception cref="System.Exception"/>
718717
[NUnit.Framework.Test]
718+
[LogMessage(iText.IO.LogMessageConstant.ELEMENT_DOES_NOT_FIT_AREA, Count = 2)]
719719
public virtual void FloatsOnPageSplit01() {
720720
String cmpFileName = sourceFolder + "cmp_floatsOnPageSplit01.pdf";
721721
String outFile = destinationFolder + "floatsOnPageSplit01.pdf";
@@ -778,6 +778,7 @@ public virtual void FloatsOnPageSplit03() {
778778
/// <exception cref="System.IO.IOException"/>
779779
/// <exception cref="System.Exception"/>
780780
[NUnit.Framework.Test]
781+
[LogMessage(iText.IO.LogMessageConstant.ELEMENT_DOES_NOT_FIT_AREA)]
781782
public virtual void FloatsOnPageSplit04() {
782783
String cmpFileName = sourceFolder + "cmp_floatsOnPageSplit04.pdf";
783784
String outFile = destinationFolder + "floatsOnPageSplit04.pdf";
@@ -823,20 +824,23 @@ public virtual void FloatsOnPageSplit05() {
823824
/// <exception cref="System.IO.IOException"/>
824825
/// <exception cref="System.Exception"/>
825826
[NUnit.Framework.Test]
827+
[NUnit.Framework.Ignore("DEVSIX-1437")]
826828
public virtual void FloatsOnPageSplit06() {
827-
// TODO what if overflow renderer is not null already?? at the end of blockRenderer
828829
String cmpFileName = sourceFolder + "cmp_floatsOnPageSplit06.pdf";
829830
String outFile = destinationFolder + "floatsOnPageSplit06.pdf";
830831
Document document = new Document(new PdfDocument(new PdfWriter(outFile)));
831832
document.Add(new Paragraph(text + text));
832833
Div div = new Div().SetBorder(new SolidBorder(Color.RED, 2));
833834
div.SetHeight(600);
835+
// TODO Setting fixed height for the div, that will be split between pages.
834836
iText.Layout.Element.Image img = new iText.Layout.Element.Image(ImageDataFactory.Create(sourceFolder + "itis.jpg"
835837
)).SetHeight(400);
836838
img.SetProperty(Property.FLOAT, FloatPropertyValue.RIGHT);
837839
div.Add(img);
840+
// TODO Adding float that will not fit on the first page.
838841
div.Add(new Paragraph("some small text"));
839842
document.Add(div);
843+
// TODO div height shall be correct on the second page.
840844
document.Close();
841845
NUnit.Framework.Assert.IsNull(new CompareTool().CompareByContent(outFile, cmpFileName, destinationFolder,
842846
"diff22_"));
@@ -845,8 +849,8 @@ public virtual void FloatsOnPageSplit06() {
845849
/// <exception cref="System.IO.IOException"/>
846850
/// <exception cref="System.Exception"/>
847851
[NUnit.Framework.Test]
852+
[NUnit.Framework.Ignore("DEVSIX-1437")]
848853
public virtual void FloatsOnPageSplit07() {
849-
// TODO floats with nothing overflowed, next normal kid returned NOTHING
850854
String cmpFileName = sourceFolder + "cmp_floatsOnPageSplit07.pdf";
851855
String outFile = destinationFolder + "floatsOnPageSplit07.pdf";
852856
Document document = new Document(new PdfDocument(new PdfWriter(outFile)));
@@ -855,11 +859,13 @@ public virtual void FloatsOnPageSplit07() {
855859
containerDiv.SetBorder(new SolidBorder(Color.MAGENTA, 2));
856860
Div div = new Div().SetBorder(new SolidBorder(Color.RED, 2));
857861
iText.Layout.Element.Image img = new iText.Layout.Element.Image(ImageDataFactory.Create(sourceFolder + "itis.jpg"
858-
)).SetHeight(400);
862+
)).SetHeight(200);
859863
div.Add(img);
860864
div.SetProperty(Property.FLOAT, FloatPropertyValue.RIGHT);
861865
containerDiv.Add(div);
866+
// TODO Adding float that WILL fit on the first page.
862867
containerDiv.Add(img);
868+
// TODO Adding that shall be overflowed to the next page. containerDiv occupied area shall not have zero height on first page.
863869
document.Add(containerDiv);
864870
document.Close();
865871
NUnit.Framework.Assert.IsNull(new CompareTool().CompareByContent(outFile, cmpFileName, destinationFolder,
@@ -869,6 +875,7 @@ public virtual void FloatsOnPageSplit07() {
869875
/// <exception cref="System.IO.IOException"/>
870876
/// <exception cref="System.Exception"/>
871877
[NUnit.Framework.Test]
878+
[NUnit.Framework.Ignore("DEVSIX-1437")]
872879
public virtual void FloatsOnPageSplit08() {
873880
String cmpFileName = sourceFolder + "cmp_floatsOnPageSplit08.pdf";
874881
String outFile = destinationFolder + "floatsOnPageSplit08.pdf";
@@ -880,9 +887,11 @@ public virtual void FloatsOnPageSplit08() {
880887
iText.Layout.Element.Image img = new iText.Layout.Element.Image(ImageDataFactory.Create(sourceFolder + "itis.jpg"
881888
)).SetHeight(400);
882889
div.Add(img);
890+
// TODO Adding image that will not fit on first page to float.
883891
div.SetProperty(Property.FLOAT, FloatPropertyValue.RIGHT);
884892
containerDiv.Add(div);
885893
containerDiv.Add(img);
894+
// TODO Adding normal image that will not fit on the first page.
886895
document.Add(containerDiv);
887896
document.Close();
888897
NUnit.Framework.Assert.IsNull(new CompareTool().CompareByContent(outFile, cmpFileName, destinationFolder,
@@ -918,8 +927,8 @@ public virtual void FloatsOnPageSplit09() {
918927
/// <exception cref="System.IO.IOException"/>
919928
/// <exception cref="System.Exception"/>
920929
[NUnit.Framework.Test]
930+
[LogMessage(iText.IO.LogMessageConstant.ELEMENT_DOES_NOT_FIT_AREA)]
921931
public virtual void FloatsOnPageSplit10() {
922-
// TODO what if only floats are kids and all returned NOTHING - should return NOTHING
923932
String cmpFileName = sourceFolder + "cmp_floatsOnPageSplit10.pdf";
924933
String outFile = destinationFolder + "floatsOnPageSplit10.pdf";
925934
Document document = new Document(new PdfDocument(new PdfWriter(outFile)));
@@ -941,8 +950,8 @@ public virtual void FloatsOnPageSplit10() {
941950
/// <exception cref="System.IO.IOException"/>
942951
/// <exception cref="System.Exception"/>
943952
[NUnit.Framework.Test]
953+
[NUnit.Framework.Ignore("DEVSIX-1437")]
944954
public virtual void FloatsOnPageSplit11() {
945-
// TODO if some float returned NOTHING - all other floats should not be placed
946955
String cmpFileName = sourceFolder + "cmp_floatsOnPageSplit11.pdf";
947956
String outFile = destinationFolder + "floatsOnPageSplit11.pdf";
948957
Document document = new Document(new PdfDocument(new PdfWriter(outFile)));
@@ -955,14 +964,54 @@ public virtual void FloatsOnPageSplit11() {
955964
div.Add(img);
956965
div.SetProperty(Property.FLOAT, FloatPropertyValue.RIGHT);
957966
containerDiv.Add(div);
967+
// TODO Adding float that will not fit.
958968
Div div2 = new Div().SetBorder(new SolidBorder(Color.RED, 2));
959969
div2.Add(new Paragraph(text)).SetWidth(300);
960970
div2.SetProperty(Property.FLOAT, FloatPropertyValue.RIGHT);
961971
containerDiv.Add(div2);
972+
// TODO Adding float that shall be after the previous float.
962973
document.Add(containerDiv);
963974
document.Close();
964975
NUnit.Framework.Assert.IsNull(new CompareTool().CompareByContent(outFile, cmpFileName, destinationFolder,
965-
"diff21_"));
976+
"diff31_"));
977+
}
978+
979+
/// <exception cref="System.IO.IOException"/>
980+
/// <exception cref="System.Exception"/>
981+
[NUnit.Framework.Test]
982+
[NUnit.Framework.Ignore("DEVSIX-1437")]
983+
public virtual void FloatsOnPageSplit12() {
984+
String cmpFileName = sourceFolder + "cmp_floatsOnPageSplit12.pdf";
985+
String outFile = destinationFolder + "floatsOnPageSplit12.pdf";
986+
Document document = new Document(new PdfDocument(new PdfWriter(outFile)));
987+
Div div = new Div().SetBorder(new SolidBorder(Color.RED, 2));
988+
iText.Layout.Element.Image img = new iText.Layout.Element.Image(ImageDataFactory.Create(sourceFolder + "itis.jpg"
989+
)).SetHeight(400).SetWidth(100);
990+
img.SetProperty(Property.FLOAT, FloatPropertyValue.RIGHT);
991+
div.SetHeight(300).Add(img);
992+
// TODO Div shall have height of 300pt.
993+
document.Add(div);
994+
document.Close();
995+
NUnit.Framework.Assert.IsNull(new CompareTool().CompareByContent(outFile, cmpFileName, destinationFolder,
996+
"diff32_"));
997+
}
998+
999+
/// <exception cref="System.IO.IOException"/>
1000+
/// <exception cref="System.Exception"/>
1001+
[NUnit.Framework.Test]
1002+
[NUnit.Framework.Ignore("DEVSIX-1437")]
1003+
public virtual void FloatsOnPageSplit13() {
1004+
String cmpFileName = sourceFolder + "cmp_floatsOnPageSplit13.pdf";
1005+
String outFile = destinationFolder + "floatsOnPageSplit13.pdf";
1006+
Document document = new Document(new PdfDocument(new PdfWriter(outFile)));
1007+
Div div = new Div().SetBorder(new SolidBorder(Color.RED, 2));
1008+
Paragraph p = new Paragraph(text);
1009+
p.SetProperty(Property.FLOAT, FloatPropertyValue.RIGHT);
1010+
div.SetHeight(100).Add(p);
1011+
document.Add(div);
1012+
document.Close();
1013+
NUnit.Framework.Assert.IsNull(new CompareTool().CompareByContent(outFile, cmpFileName, destinationFolder,
1014+
"diff32_"));
9661015
}
9671016
}
9681017
}
Binary file not shown.

itext/itext.layout/itext/layout/renderer/BlockRenderer.cs

Lines changed: 42 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -147,25 +147,33 @@ public override LayoutResult Layout(LayoutContext layoutContext) {
147147
if (marginsCollapsingEnabled && !isCellRenderer) {
148148
marginsCollapseHandler.EndMarginsCollapse(layoutBox);
149149
}
150+
FloatingHelper.IncludeChildFloatsInOccupiedArea(floatRendererAreas, this);
150151
result = new LayoutResult(LayoutResult.NOTHING, null, null, childRenderer);
151-
AbstractRenderer[] splitAndOverflowRenderers = CreateSplitAndOverflowRenderers(childPos, LayoutResult.PARTIAL
152-
, result, waitingFloatsSplitRenderers, waitingOverflowFloatRenderers);
152+
int layoutResult = anythingPlaced ? LayoutResult.PARTIAL : LayoutResult.NOTHING;
153+
AbstractRenderer[] splitAndOverflowRenderers = CreateSplitAndOverflowRenderers(childPos, layoutResult, result
154+
, waitingFloatsSplitRenderers, waitingOverflowFloatRenderers);
153155
AbstractRenderer splitRenderer = splitAndOverflowRenderers[0];
154156
AbstractRenderer overflowRenderer = splitAndOverflowRenderers[1];
155-
Rectangle splitRendererOccupiedArea = splitRenderer.GetOccupiedArea().GetBBox();
156-
splitRendererOccupiedArea.IncreaseHeight(splitRendererOccupiedArea.GetY() - layoutBox.GetY()).SetY(layoutBox
157-
.GetY());
158157
UpdateHeightsOnSplit(wasHeightClipped, overflowRenderer);
159158
ApplyPaddings(occupiedArea.GetBBox(), paddings, true);
160159
ApplyBorderBox(occupiedArea.GetBBox(), borders, true);
161160
ApplyMargins(occupiedArea.GetBBox(), true);
162-
LayoutArea editedArea = FloatingHelper.AdjustResultOccupiedAreaForFloatAndClear(this, floatRendererAreas,
163-
parentBBox, clearHeightCorrection, marginsCollapsingEnabled);
164-
if (wasHeightClipped) {
165-
return new LayoutResult(LayoutResult.FULL, editedArea, splitRenderer, null);
161+
if (true.Equals(GetPropertyAsBoolean(Property.FORCED_PLACEMENT)) || wasHeightClipped) {
162+
LayoutArea editedArea = FloatingHelper.AdjustResultOccupiedAreaForFloatAndClear(this, layoutContext.GetFloatRendererAreas
163+
(), layoutContext.GetArea().GetBBox(), clearHeightCorrection, marginsCollapsingEnabled);
164+
return new LayoutResult(LayoutResult.FULL, editedArea, splitRenderer, null, null);
166165
}
167166
else {
168-
return new LayoutResult(LayoutResult.PARTIAL, editedArea, splitRenderer, overflowRenderer, causeOfNothing);
167+
if (layoutResult != LayoutResult.NOTHING) {
168+
LayoutArea editedArea = FloatingHelper.AdjustResultOccupiedAreaForFloatAndClear(this, layoutContext.GetFloatRendererAreas
169+
(), layoutContext.GetArea().GetBBox(), clearHeightCorrection, marginsCollapsingEnabled);
170+
return new LayoutResult(layoutResult, editedArea, splitRenderer, overflowRenderer, null).SetAreaBreak(result
171+
.GetAreaBreak());
172+
}
173+
else {
174+
return new LayoutResult(layoutResult, null, null, overflowRenderer, result.GetCauseOfNothing()).SetAreaBreak
175+
(result.GetAreaBreak());
176+
}
169177
}
170178
}
171179
if (marginsCollapsingEnabled) {
@@ -195,9 +203,8 @@ public override LayoutResult Layout(LayoutContext layoutContext) {
195203
()));
196204
}
197205
}
198-
if (FloatingHelper.IsRendererFloating(this) || isCellRenderer) {
199-
FloatingHelper.IncludeChildFloatsInOccupiedArea(floatRendererAreas, this);
200-
}
206+
// On page split, content will be drawn on next page, i.e. under all floats on this page
207+
FloatingHelper.IncludeChildFloatsInOccupiedArea(floatRendererAreas, this);
201208
if (result.GetSplitRenderer() != null) {
202209
// Use occupied area's bbox width so that for absolutely positioned renderers we do not align using full width
203210
// in case when parent box should wrap around child boxes.
@@ -298,7 +305,7 @@ public override LayoutResult Layout(LayoutContext layoutContext) {
298305
}
299306
}
300307
}
301-
anythingPlaced = true;
308+
anythingPlaced = anythingPlaced || result.GetStatus() != LayoutResult.NOTHING;
302309
if (result.GetOccupiedArea() != null) {
303310
if (!FloatingHelper.IsRendererFloating(childRenderer)) {
304311
// this check is needed only if margins collapsing is enabled
@@ -392,24 +399,37 @@ public override LayoutResult Layout(LayoutContext layoutContext) {
392399
}
393400
ApplyVerticalAlignment();
394401
FloatingHelper.RemoveFloatsAboveRendererBottom(floatRendererAreas, this);
402+
int layoutResult_1 = LayoutResult.FULL;
403+
if (overflowRenderer_1 != null || !waitingOverflowFloatRenderers.IsEmpty()) {
404+
// TODO as we still might have kids (floats) to process, we shall be able to support "NOTHING", "wasHeightClipped => return FULL" and "FORCED_PLACEMENT" cases
405+
layoutResult_1 = !anythingPlaced && !waitingOverflowFloatRenderers.IsEmpty() ? LayoutResult.NOTHING : LayoutResult
406+
.PARTIAL;
407+
}
395408
if (!waitingOverflowFloatRenderers.IsEmpty()) {
396-
overflowRenderer_1 = CreateOverflowRenderer(LayoutResult.PARTIAL);
409+
if (overflowRenderer_1 == null || layoutResult_1 == LayoutResult.NOTHING) {
410+
overflowRenderer_1 = CreateOverflowRenderer(layoutResult_1);
411+
}
397412
overflowRenderer_1.GetChildRenderers().AddAll(waitingOverflowFloatRenderers);
398413
}
399414
AbstractRenderer splitRenderer_1 = this;
400415
if (!waitingFloatsSplitRenderers.IsEmpty()) {
401-
splitRenderer_1 = CreateSplitRenderer(LayoutResult.PARTIAL);
416+
splitRenderer_1 = CreateSplitRenderer(layoutResult_1);
402417
splitRenderer_1.childRenderers = new List<IRenderer>(childRenderers);
403418
ReplaceSplitRendererKidFloats(waitingFloatsSplitRenderers, splitRenderer_1);
404419
}
405-
LayoutArea editedArea_1 = FloatingHelper.AdjustResultOccupiedAreaForFloatAndClear(this, layoutContext.GetFloatRendererAreas
406-
(), layoutContext.GetArea().GetBBox(), clearHeightCorrection, marginsCollapsingEnabled);
407-
if (overflowRenderer_1 == null) {
408-
return new LayoutResult(LayoutResult.FULL, editedArea_1, splitRenderer_1, null, causeOfNothing);
420+
if (layoutResult_1 == LayoutResult.NOTHING) {
421+
return new LayoutResult(LayoutResult.NOTHING, null, null, overflowRenderer_1, causeOfNothing);
409422
}
410423
else {
411-
return new LayoutResult(LayoutResult.PARTIAL, editedArea_1, splitRenderer_1, overflowRenderer_1, causeOfNothing
412-
);
424+
LayoutArea editedArea = FloatingHelper.AdjustResultOccupiedAreaForFloatAndClear(this, layoutContext.GetFloatRendererAreas
425+
(), layoutContext.GetArea().GetBBox(), clearHeightCorrection, marginsCollapsingEnabled);
426+
if (overflowRenderer_1 == null) {
427+
return new LayoutResult(LayoutResult.FULL, editedArea, splitRenderer_1, null, causeOfNothing);
428+
}
429+
else {
430+
return new LayoutResult(LayoutResult.PARTIAL, editedArea, splitRenderer_1, overflowRenderer_1, causeOfNothing
431+
);
432+
}
413433
}
414434
}
415435

port-hash

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
a30b527d46b3c88b2012db25561ae0928181e171
1+
f430c0de001c3d331b024da20cca9fe04c130a36

0 commit comments

Comments
 (0)