Skip to content

Commit 21c9b38

Browse files
author
Eugene Bochilo
committed
Support box-sizing property in case of FlexContainerRenderer
DEVSIX-5168
1 parent 8a7a465 commit 21c9b38

File tree

31 files changed

+138
-28
lines changed

31 files changed

+138
-28
lines changed

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2512,14 +2512,14 @@ private void adjustPositionedRendererLayoutBoxWidth(IRenderer renderer, Rectangl
25122512
}
25132513
}
25142514

2515-
private static float calculatePaddingBorderWidth(AbstractRenderer renderer) {
2515+
static float calculatePaddingBorderWidth(AbstractRenderer renderer) {
25162516
Rectangle dummy = new Rectangle(0, 0);
25172517
renderer.applyBorderBox(dummy, true);
25182518
renderer.applyPaddings(dummy, true);
25192519
return dummy.getWidth();
25202520
}
25212521

2522-
private static float calculatePaddingBorderHeight(AbstractRenderer renderer) {
2522+
static float calculatePaddingBorderHeight(AbstractRenderer renderer) {
25232523
Rectangle dummy = new Rectangle(0, 0);
25242524
renderer.applyBorderBox(dummy, true);
25252525
renderer.applyPaddings(dummy, true);

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

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,14 @@ public LayoutResult layout(LayoutContext layoutContext) {
9494
final List<UnitValue> previousMinHeights = new ArrayList<>();
9595
for (final List<FlexItemInfo> line : lines) {
9696
for (final FlexItemInfo itemInfo : line) {
97-
final Rectangle rectangleWithoutBordersMarginsPaddings =
98-
itemInfo.getRenderer().applyMarginsBordersPaddings(itemInfo.getRectangle().clone(), false);
97+
final Rectangle rectangleWithoutBordersMarginsPaddings;
98+
if (AbstractRenderer.isBorderBoxSizing(itemInfo.getRenderer())) {
99+
rectangleWithoutBordersMarginsPaddings =
100+
itemInfo.getRenderer().applyMargins(itemInfo.getRectangle().clone(), false);
101+
} else {
102+
rectangleWithoutBordersMarginsPaddings =
103+
itemInfo.getRenderer().applyMarginsBordersPaddings(itemInfo.getRectangle().clone(), false);
104+
}
99105

100106
previousWidths.add(itemInfo.getRenderer().<UnitValue>getProperty(Property.WIDTH));
101107
previousHeights.add(itemInfo.getRenderer().<UnitValue>getProperty(Property.HEIGHT));

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

Lines changed: 46 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -86,9 +86,6 @@ public static List<List<FlexItemInfo>> calculateChildrenRectangles(Rectangle fle
8686
Rectangle layoutBox = flexContainerBBox.clone();
8787
flexContainerRenderer.applyMarginsBordersPaddings(layoutBox, false);
8888

89-
List<FlexItemCalculationInfo> flexItemCalculationInfos =
90-
createFlexItemCalculationInfos(flexContainerRenderer, layoutBox);
91-
9289
// 9.2. Line Length Determination
9390

9491
// 2. Determine the available main and cross space for the flex items.
@@ -106,7 +103,10 @@ public static List<List<FlexItemInfo>> calculateChildrenRectangles(Rectangle fle
106103
Float minCrossSize = flexContainerRenderer.retrieveMinHeight();
107104
Float maxCrossSize = flexContainerRenderer.retrieveMaxHeight();
108105

109-
determineFlexBasisAndHypotheticalMainSizeForFlexItems(flexItemCalculationInfos, (float) mainSize);
106+
List<FlexItemCalculationInfo> flexItemCalculationInfos =
107+
createFlexItemCalculationInfos(flexContainerRenderer, (float) mainSize);
108+
109+
determineFlexBasisAndHypotheticalMainSizeForFlexItems(flexItemCalculationInfos);
110110

111111
// 9.3. Main Size Determination
112112

@@ -182,17 +182,12 @@ public static List<List<FlexItemInfo>> calculateChildrenRectangles(Rectangle fle
182182
}
183183

184184
static void determineFlexBasisAndHypotheticalMainSizeForFlexItems(
185-
List<FlexItemCalculationInfo> flexItemCalculationInfos, float mainSize) {
185+
List<FlexItemCalculationInfo> flexItemCalculationInfos) {
186186
for (FlexItemCalculationInfo info : flexItemCalculationInfos) {
187187
// 3. Determine the flex base size and hypothetical main size of each item:
188188

189-
// Note: We assume that flex-basis: auto was resolved (set to either width or height) on some upper level
190-
assert null != info.flexBasis;
191-
192189
// A. If the item has a definite used flex basis, that’s the flex base size.
193-
info.flexBaseSize = info.flexBasis.isPercentValue()
194-
? (info.flexBasis.getValue() * mainSize / 100)
195-
: info.flexBasis.getValue();
190+
info.flexBaseSize = info.flexBasis;
196191

197192
// TODO DEVSIX-5001 content as width are not supported
198193
// TODO DEVSIX-5004 Implement method to check whether an element has an intrinsic aspect ratio
@@ -607,34 +602,64 @@ static boolean isZero(final float value) {
607602
}
608603

609604
private static List<FlexItemCalculationInfo> createFlexItemCalculationInfos(
610-
FlexContainerRenderer flexContainerRenderer, Rectangle flexContainerBBox) {
605+
FlexContainerRenderer flexContainerRenderer, float flexContainerWidth) {
611606
final List<IRenderer> childRenderers = flexContainerRenderer.getChildRenderers();
612607
final List<FlexItemCalculationInfo> flexItems = new ArrayList<>();
613608
for (final IRenderer renderer : childRenderers) {
614609
if (renderer instanceof AbstractRenderer) {
615610
AbstractRenderer abstractRenderer = (AbstractRenderer) renderer;
616-
float flexGrow = (float) renderer.<Float>getProperty(Property.FLEX_GROW, FLEX_GROW_INITIAL_VALUE);
617-
618-
float flexShrink = (float) renderer.<Float>getProperty(Property.FLEX_SHRINK, FLEX_SHRINK_INITIAL_VALUE);
619611

620612
// TODO DEVSIX-5091 improve determining of the flex base size when flex-basis: content
621-
float maxWidth = abstractRenderer.getMinMaxWidth().getMaxWidth();
622-
maxWidth = abstractRenderer.applyMarginsBordersPaddings(new Rectangle(maxWidth, 0), false).getWidth();
613+
float maxWidth = calculateMaxWidth(abstractRenderer, flexContainerWidth);
614+
float flexBasis;
615+
if (renderer.<UnitValue>getProperty(Property.FLEX_BASIS) == null) {
616+
flexBasis = maxWidth;
617+
} else {
618+
flexBasis = (float) abstractRenderer.retrieveUnitValue(flexContainerWidth, Property.FLEX_BASIS);
619+
if (AbstractRenderer.isBorderBoxSizing(abstractRenderer)) {
620+
flexBasis -= AbstractRenderer.calculatePaddingBorderWidth(abstractRenderer);
621+
}
622+
}
623+
flexBasis = Math.max(flexBasis, 0);
623624

624-
UnitValue flexBasis = renderer.getProperty(Property.FLEX_BASIS, UnitValue.createPointValue(maxWidth));
625+
float flexGrow = (float) renderer.<Float>getProperty(Property.FLEX_GROW, FLEX_GROW_INITIAL_VALUE);
626+
627+
float flexShrink = (float) renderer.<Float>getProperty(Property.FLEX_SHRINK, FLEX_SHRINK_INITIAL_VALUE);
625628

626629
final FlexItemCalculationInfo flexItemInfo = new FlexItemCalculationInfo(
627-
(AbstractRenderer) renderer, flexBasis, flexGrow, flexShrink, flexContainerBBox.getWidth());
630+
(AbstractRenderer) renderer, flexBasis, flexGrow, flexShrink, flexContainerWidth);
628631

629632
flexItems.add(flexItemInfo);
630633
}
631634
}
632635
return flexItems;
633636
}
634637

638+
private static float calculateMaxWidth(AbstractRenderer flexItemRenderer, float flexContainerWidth) {
639+
Float maxWidth;
640+
if (flexItemRenderer instanceof TableRenderer) {
641+
// TODO DEVSIX-5214 we can't call TableRenderer#retrieveWidth method as far as it can throw NPE
642+
maxWidth = flexItemRenderer.getMinMaxWidth().getMaxWidth();
643+
maxWidth = flexItemRenderer.applyMarginsBordersPaddings(
644+
new Rectangle((float) maxWidth, 0), false).getWidth();
645+
} else {
646+
// We need to retrieve width and max-width manually because this methods take into account box-sizing
647+
maxWidth = flexItemRenderer.retrieveWidth(flexContainerWidth);
648+
if (maxWidth == null) {
649+
maxWidth = flexItemRenderer.retrieveMaxWidth(flexContainerWidth);
650+
}
651+
if (maxWidth == null) {
652+
maxWidth = flexItemRenderer.getMinMaxWidth().getMaxWidth();
653+
maxWidth = flexItemRenderer.applyMarginsBordersPaddings(
654+
new Rectangle((float) maxWidth, 0), false).getWidth();
655+
}
656+
}
657+
return (float) maxWidth;
658+
}
659+
635660
static class FlexItemCalculationInfo {
636661
AbstractRenderer renderer;
637-
UnitValue flexBasis;
662+
float flexBasis;
638663
float flexShrink;
639664
float flexGrow;
640665
float minContent;
@@ -656,12 +681,9 @@ static class FlexItemCalculationInfo {
656681
float hypotheticalMainSize;
657682
float hypotheticalCrossSize;
658683

659-
public FlexItemCalculationInfo(AbstractRenderer renderer, UnitValue flexBasis,
684+
public FlexItemCalculationInfo(AbstractRenderer renderer, float flexBasis,
660685
float flexGrow, float flexShrink, float areaWidth) {
661686
this.renderer = renderer;
662-
if (null == flexBasis) {
663-
throw new IllegalArgumentException(LayoutExceptionMessageConstant.FLEX_BASIS_CANNOT_BE_NULL);
664-
}
665687
this.flexBasis = flexBasis;
666688
if (flexShrink < 0) {
667689
throw new IllegalArgumentException(LayoutExceptionMessageConstant.FLEX_SHRINK_CANNOT_BE_NEGATIVE);

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

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ This file is part of the iText (R) project.
3333
import com.itextpdf.layout.borders.SolidBorder;
3434
import com.itextpdf.layout.property.AlignmentPropertyValue;
3535
import com.itextpdf.layout.property.Background;
36+
import com.itextpdf.layout.property.BoxSizingPropertyValue;
3637
import com.itextpdf.layout.property.JustifyContent;
3738
import com.itextpdf.layout.property.ListNumberingType;
3839
import com.itextpdf.layout.property.OverflowPropertyValue;
@@ -966,6 +967,87 @@ public void collapsingMarginsFlexContainerTest() throws IOException, Interrupted
966967
Assert.assertNull(new CompareTool().compareByContent(outFileName, cmpFileName, destinationFolder, "diff"));
967968
}
968969

970+
@Test
971+
public void flexItemBoxSizingTest() throws IOException, InterruptedException {
972+
String outFileName = destinationFolder + "flexItemBoxSizingTest" + comparisonPdfId + ".pdf";
973+
String cmpFileName = sourceFolder + "cmp_flexItemBoxSizingTest" + comparisonPdfId + ".pdf";
974+
PdfDocument pdfDocument = new PdfDocument(new PdfWriter(outFileName));
975+
976+
Document document = new Document(pdfDocument);
977+
978+
Div flexContainer = createFlexContainer();
979+
flexContainer.setProperty(Property.BORDER, new SolidBorder(ColorConstants.BLUE, 30));
980+
flexContainer.setProperty(Property.BACKGROUND, new Background(ColorConstants.LIGHT_GRAY));
981+
flexContainer.setWidth(450);
982+
flexContainer.setHeight(200);
983+
984+
Div innerDiv = new Div();
985+
innerDiv.setWidth(120);
986+
innerDiv.setHeight(120);
987+
innerDiv.setProperty(Property.BOX_SIZING, BoxSizingPropertyValue.BORDER_BOX);
988+
innerDiv.setProperty(Property.BACKGROUND, new Background(ColorConstants.GREEN));
989+
innerDiv.setBorder(new SolidBorder(ColorConstants.RED, 20));
990+
innerDiv.setProperty(Property.FLEX_GROW, 0.3F);
991+
992+
Div innerDiv2 = new Div();
993+
innerDiv2.setProperty(Property.FLEX_BASIS, UnitValue.createPointValue(120));
994+
innerDiv2.setProperty(Property.BOX_SIZING, BoxSizingPropertyValue.BORDER_BOX);
995+
innerDiv2.setProperty(Property.BACKGROUND, new Background(ColorConstants.GREEN));
996+
innerDiv2.setBorder(new SolidBorder(ColorConstants.RED, 20));
997+
innerDiv2.setProperty(Property.FLEX_GROW, 0.3F);
998+
999+
Div innerDiv3 = new Div();
1000+
innerDiv3.setProperty(Property.BOX_SIZING, BoxSizingPropertyValue.BORDER_BOX);
1001+
innerDiv3.setProperty(Property.BACKGROUND, new Background(ColorConstants.GREEN));
1002+
innerDiv3.setBorder(new SolidBorder(ColorConstants.RED, 20));
1003+
1004+
Div innerDivChild =
1005+
new Div().setBorder(new SolidBorder(ColorConstants.ORANGE, 10)).setBackgroundColor(ColorConstants.PINK).setWidth(50).setHeight(50);
1006+
innerDivChild.setProperty(Property.BOX_SIZING, BoxSizingPropertyValue.BORDER_BOX);
1007+
innerDiv.add(innerDivChild);
1008+
innerDiv2.add(innerDivChild);
1009+
innerDiv3.add(innerDivChild);
1010+
1011+
Div divToCompare = new Div().setWidth(450).setHeight(100).setBackgroundColor(ColorConstants.MAGENTA).setMarginTop(50);
1012+
1013+
flexContainer.add(innerDiv).add(innerDiv2).add(innerDiv3);
1014+
document.add(flexContainer).add(divToCompare);
1015+
document.close();
1016+
1017+
Assert.assertNull(new CompareTool().compareByContent(outFileName, cmpFileName, destinationFolder, "diff"));
1018+
}
1019+
1020+
@Test
1021+
public void flexContainerBoxSizingTest() throws IOException, InterruptedException {
1022+
String outFileName = destinationFolder + "flexContainerBoxSizingTest" + comparisonPdfId + ".pdf";
1023+
String cmpFileName = sourceFolder + "cmp_flexContainerBoxSizingTest" + comparisonPdfId + ".pdf";
1024+
PdfDocument pdfDocument = new PdfDocument(new PdfWriter(outFileName));
1025+
1026+
Document document = new Document(pdfDocument);
1027+
1028+
Div flexContainer = createFlexContainer();
1029+
flexContainer.setProperty(Property.BORDER, new SolidBorder(ColorConstants.BLUE, 30));
1030+
flexContainer.setProperty(Property.BACKGROUND, new Background(ColorConstants.LIGHT_GRAY));
1031+
flexContainer.setWidth(450);
1032+
flexContainer.setProperty(Property.BOX_SIZING, BoxSizingPropertyValue.BORDER_BOX);
1033+
1034+
Div innerDiv = new Div();
1035+
innerDiv.setWidth(120);
1036+
Div innerDivChild =
1037+
new Div().setBorder(new SolidBorder(ColorConstants.ORANGE, 10)).setBackgroundColor(ColorConstants.PINK).setWidth(100).setHeight(100);
1038+
innerDiv.add(innerDivChild);
1039+
innerDiv.setProperty(Property.BACKGROUND, new Background(ColorConstants.GREEN));
1040+
innerDiv.setBorder(new SolidBorder(ColorConstants.RED, 20));
1041+
1042+
Div divToCompare = new Div().setWidth(450).setHeight(100).setBackgroundColor(ColorConstants.MAGENTA).setMarginTop(50);
1043+
1044+
flexContainer.add(innerDiv).add(createNewDiv());
1045+
document.add(flexContainer).add(divToCompare);
1046+
document.close();
1047+
1048+
Assert.assertNull(new CompareTool().compareByContent(outFileName, cmpFileName, destinationFolder, "diff"));
1049+
}
1050+
9691051
private Div getFlexContainer(OverflowPropertyValue overflowX, Style style) {
9701052
FlexContainer flexContainer = createFlexContainer();
9711053
flexContainer

0 commit comments

Comments
 (0)