Skip to content

Commit 110246b

Browse files
ars18wrwiText-CI
authored andcommitted
Respect width when placing flex container
Flex items may overflow, but the container's width should be repsected DEVSIX-5098
1 parent 0afef32 commit 110246b

16 files changed

+146
-11
lines changed

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ public LayoutResult layout(LayoutContext layoutContext) {
244244
|| Boolean.TRUE.equals(getPropertyAsBoolean(Property.FILL_AVAILABLE_AREA))) {
245245
occupiedArea.setBBox(Rectangle.getCommonRectangle(occupiedArea.getBBox(), layoutBox));
246246
} else if (result.getOccupiedArea() != null && result.getStatus() != LayoutResult.NOTHING) {
247-
occupiedArea.setBBox(Rectangle.getCommonRectangle(occupiedArea.getBBox(), result.getOccupiedArea().getBBox()));
247+
recalculateOccupiedAreaAfterChildLayout(result.getOccupiedArea().getBBox(), blockMaxHeight);
248248
fixOccupiedAreaIfOverflowedX(overflowX, layoutBox);
249249
}
250250

@@ -325,7 +325,7 @@ public LayoutResult layout(LayoutContext layoutContext) {
325325

326326
// The second condition check (after &&) is needed only if margins collapsing is enabled
327327
if (result.getOccupiedArea() != null && (!FloatingHelper.isRendererFloating(childRenderer) || includeFloatsInOccupiedArea)) {
328-
recalculateOccupiedAreaAfterChildLayout(result);
328+
recalculateOccupiedAreaAfterChildLayout(result.getOccupiedArea().getBBox(), blockMaxHeight);
329329
fixOccupiedAreaIfOverflowedX(overflowX, layoutBox);
330330
}
331331
if (marginsCollapsingEnabled) {
@@ -584,8 +584,8 @@ protected AbstractRenderer createOverflowRenderer(int layoutResult) {
584584
return overflowRenderer;
585585
}
586586

587-
void recalculateOccupiedAreaAfterChildLayout(LayoutResult result) {
588-
occupiedArea.setBBox(Rectangle.getCommonRectangle(occupiedArea.getBBox(), result.getOccupiedArea().getBBox()));
587+
void recalculateOccupiedAreaAfterChildLayout(Rectangle resultBBox, Float blockMaxHeight) {
588+
occupiedArea.setBBox(Rectangle.getCommonRectangle(occupiedArea.getBBox(), resultBBox));
589589
}
590590

591591
Rectangle recalculateLayoutBoxBeforeChildLayout(Rectangle layoutBox,

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

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ This file is part of the iText (R) project.
5050
import com.itextpdf.layout.layout.LayoutResult;
5151
import com.itextpdf.layout.minmaxwidth.MinMaxWidth;
5252
import com.itextpdf.layout.minmaxwidth.MinMaxWidthUtils;
53+
import com.itextpdf.layout.property.OverflowPropertyValue;
5354
import com.itextpdf.layout.property.Property;
5455
import com.itextpdf.layout.property.UnitValue;
5556

@@ -238,13 +239,25 @@ boolean stopLayoutingChildrenIfChildResultNotFull(LayoutResult returnResult) {
238239
return returnResult.getStatus() != LayoutResult.FULL;
239240
}
240241

242+
/**
243+
* {@inheritDoc}
244+
*/
241245
@Override
242-
void recalculateOccupiedAreaAfterChildLayout(LayoutResult result) {
243-
// TODO DEVSIX-5098 Occupied area shall not be bigger than width or max-width
244-
Rectangle recalculatedRectangle =
245-
Rectangle.getCommonRectangle(occupiedArea.getBBox(), result.getOccupiedArea().getBBox());
246+
void recalculateOccupiedAreaAfterChildLayout(Rectangle resultBBox, Float blockMaxHeight) {
247+
final Rectangle oldBBox = occupiedArea.getBBox().clone();
248+
final Rectangle recalculatedRectangle = Rectangle.getCommonRectangle(occupiedArea.getBBox(),
249+
resultBBox);
246250
occupiedArea.getBBox().setY(recalculatedRectangle.getY());
247251
occupiedArea.getBBox().setHeight(recalculatedRectangle.getHeight());
252+
if (oldBBox.getTop() < occupiedArea.getBBox().getTop()) {
253+
occupiedArea.getBBox().decreaseHeight(occupiedArea.getBBox().getTop() - oldBBox.getTop());
254+
}
255+
if (null != blockMaxHeight &&
256+
occupiedArea.getBBox().getHeight() > ((float) blockMaxHeight)) {
257+
occupiedArea.getBBox()
258+
.moveUp(occupiedArea.getBBox().getHeight() - ((float) blockMaxHeight));
259+
occupiedArea.getBBox().setHeight((float) blockMaxHeight);
260+
}
248261
}
249262

250263
@Override
@@ -282,6 +295,24 @@ private FlexItemInfo findFlexItemInfo(AbstractRenderer renderer) {
282295
return null;
283296
}
284297

298+
@Override
299+
void fixOccupiedAreaIfOverflowedX(OverflowPropertyValue overflowX, Rectangle layoutBox) {
300+
// TODO DEVSIX-5087 Support overflow visible/hidden property correctly
301+
return;
302+
}
303+
304+
/**
305+
* {@inheritDoc}
306+
*/
307+
@Override
308+
public void addChild(IRenderer renderer) {
309+
// TODO DEVSIX-5087 Since overflow-fit is an internal iText overflow value, we do not need to support if
310+
// for html/css objects, such as flex. As for now we will set VISIBLE by default, however, while working
311+
// on the ticket one may come to some more satifactory approach
312+
renderer.setProperty(Property.OVERFLOW_X, OverflowPropertyValue.VISIBLE);
313+
super.addChild(renderer);
314+
}
315+
285316
private void findMinMaxWidthIfCorrespondingPropertiesAreNotSet(MinMaxWidth minMaxWidth,
286317
AbstractWidthHandler minMaxWidthHandler) {
287318
// TODO DEVSIX-5086 When flex-wrap will be fully supported we'll find min/max width with respect to the lines

layout/src/test/java/com/itextpdf/layout/FlexContainerTest.java

Lines changed: 107 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ This file is part of the iText (R) project.
2929
import com.itextpdf.kernel.pdf.PdfWriter;
3030
import com.itextpdf.kernel.utils.CompareTool;
3131
import com.itextpdf.layout.borders.SolidBorder;
32+
import com.itextpdf.layout.element.AreaBreak;
3233
import com.itextpdf.layout.element.Div;
3334
import com.itextpdf.layout.element.FlexContainer;
3435
import com.itextpdf.layout.element.IElement;
@@ -40,6 +41,7 @@ This file is part of the iText (R) project.
4041
import com.itextpdf.layout.property.AlignmentPropertyValue;
4142
import com.itextpdf.layout.property.JustifyContent;
4243
import com.itextpdf.layout.property.ListNumberingType;
44+
import com.itextpdf.layout.property.OverflowPropertyValue;
4345
import com.itextpdf.layout.property.Property;
4446
import com.itextpdf.layout.property.UnitValue;
4547
import com.itextpdf.test.ExtendedITextTest;
@@ -77,7 +79,7 @@ public FlexContainerTest(Object alignItemsValue, Object justifyContentValue, Obj
7779
this.testNumber = (Integer) testNumber;
7880
}
7981

80-
@Parameterized.Parameters(name = "{index}: align-items: {1}; justify-content: {2}")
82+
@Parameterized.Parameters(name = "{index}: align-items: {0}; justify-content: {1}")
8183
public static Iterable<Object[]> alignItemsAndJustifyContentProperties() {
8284
return Arrays.asList(new Object[][]{
8385
{AlignmentPropertyValue.FLEX_START, JustifyContent.FLEX_START, 1},
@@ -792,8 +794,110 @@ public void flexContainerRotationAngleTest() throws IOException, InterruptedExce
792794
Assert.assertNull(new CompareTool().compareByContent(outFileName, cmpFileName, destinationFolder, "diff"));
793795
}
794796

795-
private Div createFlexContainer() {
796-
Div flexContainer = new FlexContainer();
797+
@Test
798+
// TODO DEVSIX-5174 content should overflow bottom
799+
public void respectFlexContainersHeightTest() throws IOException, InterruptedException {
800+
String outFileName = destinationFolder + "respectFlexContainersHeightTest" + testNumber + ".pdf";
801+
String cmpFileName = sourceFolder + "cmp_respectFlexContainersHeightTest" + testNumber + ".pdf";
802+
PdfDocument pdfDocument = new PdfDocument(new PdfWriter(outFileName));
803+
804+
Document document = new Document(pdfDocument);
805+
Style containerStyle = new Style()
806+
.setWidth(60)
807+
.setHeight(50);
808+
809+
Div flexContainer = getFlexContainer(null, containerStyle);
810+
Div flexItem = new Div()
811+
.setBackgroundColor(ColorConstants.BLUE)
812+
.add(new Paragraph("h"))
813+
.add(new Paragraph("e"))
814+
.add(new Paragraph("l"))
815+
.add(new Paragraph("l"))
816+
.add(new Paragraph("o"))
817+
.add(new Paragraph("w"))
818+
.add(new Paragraph("o"))
819+
.add(new Paragraph("r"))
820+
.add(new Paragraph("l"))
821+
.add(new Paragraph("d"));
822+
flexContainer.add(flexItem);
823+
flexContainer.add(new Div().setBackgroundColor(ColorConstants.YELLOW).setWidth(10).setHeight(200));
824+
825+
document.add(flexContainer);
826+
827+
document.close();
828+
829+
Assert.assertNull(new CompareTool().compareByContent(outFileName, cmpFileName, destinationFolder, "diff"));
830+
}
831+
832+
@Test
833+
public void respectFlexContainersWidthTest() throws IOException, InterruptedException {
834+
String outFileName = destinationFolder + "respectFlexContainersWidthTest" + testNumber + ".pdf";
835+
String cmpFileName = sourceFolder + "cmp_respectFlexContainersWidthTest" + testNumber + ".pdf";
836+
PdfDocument pdfDocument = new PdfDocument(new PdfWriter(outFileName));
837+
838+
Document document = new Document(pdfDocument);
839+
840+
// default (overflow fit)
841+
OverflowPropertyValue overflowX = null;
842+
Style containerStyle = new Style()
843+
.setWidth(60)
844+
.setHeight(200);
845+
846+
Style itemStyle = new Style()
847+
.setWidth(60f)
848+
.setHeight(100f);
849+
850+
Div flexContainer = getFlexContainer(overflowX, containerStyle);
851+
flexContainer
852+
.add(getFlexItem(overflowX, itemStyle))
853+
.add(getFlexItem(overflowX, itemStyle));
854+
document.add(flexContainer);
855+
856+
document.add(new AreaBreak());
857+
858+
// default (overflow visible)
859+
overflowX = OverflowPropertyValue.VISIBLE;
860+
flexContainer = getFlexContainer(overflowX, containerStyle);
861+
flexContainer
862+
.add(getFlexItem(overflowX, itemStyle))
863+
.add(getFlexItem(overflowX, itemStyle));
864+
document.add(flexContainer);
865+
866+
document.close();
867+
868+
Assert.assertNull(new CompareTool().compareByContent(outFileName, cmpFileName, destinationFolder, "diff"));
869+
}
870+
871+
private Div getFlexContainer(OverflowPropertyValue overflowX, Style style) {
872+
FlexContainer flexContainer = createFlexContainer();
873+
flexContainer
874+
.setBackgroundColor(ColorConstants.GREEN)
875+
.setBorderRight(new SolidBorder(60));
876+
if (null != style) {
877+
flexContainer.addStyle(style);
878+
}
879+
if (null != overflowX) {
880+
flexContainer.setProperty(Property.OVERFLOW_X, overflowX);
881+
}
882+
return flexContainer;
883+
}
884+
885+
private static Div getFlexItem(OverflowPropertyValue overflowX, Style style) {
886+
Div flexItem = new Div();
887+
flexItem.setProperty(Property.FLEX_GROW, 0f);
888+
flexItem.setProperty(Property.FLEX_SHRINK, 0f);
889+
if (null != style) {
890+
flexItem.addStyle(style);
891+
}
892+
flexItem.setBackgroundColor(ColorConstants.BLUE);
893+
if (null != overflowX) {
894+
flexItem.setProperty(Property.OVERFLOW_X, overflowX);
895+
}
896+
return flexItem;
897+
}
898+
899+
private FlexContainer createFlexContainer() {
900+
FlexContainer flexContainer = new FlexContainer();
797901
flexContainer.setProperty(Property.ALIGN_ITEMS, alignItemsValue);
798902
flexContainer.setProperty(Property.JUSTIFY_CONTENT, justifyContentValue);
799903
return flexContainer;

0 commit comments

Comments
 (0)