Skip to content

Commit 351f98c

Browse files
committed
Support column flex direction
DEVSIX-7619
1 parent 8e75f33 commit 351f98c

File tree

109 files changed

+887
-82
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

109 files changed

+887
-82
lines changed

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,8 @@ public LayoutResult layout(LayoutContext layoutContext) {
108108
if (rotation != null || isFixedLayout()) {
109109
parentBBox.moveDown(AbstractRenderer.INF - parentBBox.getHeight()).setHeight(AbstractRenderer.INF);
110110
}
111-
if (rotation != null && !FloatingHelper.isRendererFloating(this, floatPropertyValue)) {
111+
if (rotation != null && !FloatingHelper.isRendererFloating(this, floatPropertyValue) &&
112+
!(this instanceof FlexContainerRenderer)) {
112113
blockWidth = RotationUtils.retrieveRotatedLayoutWidth(parentBBox.getWidth(), this);
113114
}
114115
boolean includeFloatsInOccupiedArea = BlockFormattingContextUtil.isRendererCreateBfc(this);
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/*
2+
This file is part of the iText (R) project.
3+
Copyright (c) 1998-2023 Apryse Group NV
4+
Authors: Apryse Software.
5+
6+
This program is offered under a commercial and under the AGPL license.
7+
For commercial licensing, contact us at https://itextpdf.com/sales. For AGPL licensing, see below.
8+
9+
AGPL licensing:
10+
This program is free software: you can redistribute it and/or modify
11+
it under the terms of the GNU Affero General Public License as published by
12+
the Free Software Foundation, either version 3 of the License, or
13+
(at your option) any later version.
14+
15+
This program is distributed in the hope that it will be useful,
16+
but WITHOUT ANY WARRANTY; without even the implied warranty of
17+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18+
GNU Affero General Public License for more details.
19+
20+
You should have received a copy of the GNU Affero General Public License
21+
along with this program. If not, see <https://www.gnu.org/licenses/>.
22+
*/
23+
package com.itextpdf.layout.renderer;
24+
25+
import com.itextpdf.layout.properties.JustifyContent;
26+
import com.itextpdf.layout.renderer.FlexUtil.FlexItemCalculationInfo;
27+
28+
import java.util.ArrayList;
29+
import java.util.Collections;
30+
import java.util.List;
31+
32+
class BottomToTopFlexItemMainDirector extends FlexColumnItemMainDirector {
33+
BottomToTopFlexItemMainDirector() {
34+
}
35+
36+
/**
37+
* {@inheritDoc}
38+
*/
39+
@Override
40+
public <T> void applyDirectionForLine(List<T> renderers) {
41+
Collections.reverse(renderers);
42+
}
43+
44+
@Override
45+
public void applyJustifyContent(List<FlexItemCalculationInfo> line, JustifyContent justifyContent,
46+
float freeSpace) {
47+
switch (justifyContent) {
48+
case NORMAL:
49+
case END:
50+
case SELF_END:
51+
case STRETCH:
52+
case SELF_START:
53+
case START:
54+
case FLEX_START:
55+
line.get(line.size() - 1).yShift = freeSpace;
56+
break;
57+
case CENTER:
58+
line.get(line.size() - 1).yShift = freeSpace / 2;
59+
break;
60+
case FLEX_END:
61+
62+
case LEFT:
63+
64+
case RIGHT:
65+
default:
66+
// We don't need to do anything in these cases
67+
}
68+
}
69+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
This file is part of the iText (R) project.
3+
Copyright (c) 1998-2023 Apryse Group NV
4+
Authors: Apryse Software.
5+
6+
This program is offered under a commercial and under the AGPL license.
7+
For commercial licensing, contact us at https://itextpdf.com/sales. For AGPL licensing, see below.
8+
9+
AGPL licensing:
10+
This program is free software: you can redistribute it and/or modify
11+
it under the terms of the GNU Affero General Public License as published by
12+
the Free Software Foundation, either version 3 of the License, or
13+
(at your option) any later version.
14+
15+
This program is distributed in the hope that it will be useful,
16+
but WITHOUT ANY WARRANTY; without even the implied warranty of
17+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18+
GNU Affero General Public License for more details.
19+
20+
You should have received a copy of the GNU Affero General Public License
21+
along with this program. If not, see <https://www.gnu.org/licenses/>.
22+
*/
23+
package com.itextpdf.layout.renderer;
24+
25+
import java.util.ArrayList;
26+
import java.util.List;
27+
28+
abstract class FlexColumnItemMainDirector implements IFlexItemMainDirector {
29+
FlexColumnItemMainDirector() {
30+
}
31+
32+
/**
33+
* {@inheritDoc}
34+
*/
35+
@Override
36+
public List<IRenderer> applyDirection(List<List<FlexItemInfo>> lines) {
37+
List<IRenderer> renderers = new ArrayList<>();
38+
for (List<FlexItemInfo> line : lines) {
39+
applyDirectionForLine(line);
40+
for (FlexItemInfo itemInfo : line) {
41+
renderers.add(itemInfo.getRenderer());
42+
}
43+
}
44+
return renderers;
45+
}
46+
47+
/**
48+
* {@inheritDoc}
49+
*/
50+
@Override
51+
abstract public <T> void applyDirectionForLine(List<T> renderers);
52+
}

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

Lines changed: 53 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -212,14 +212,15 @@ AbstractRenderer[] createSplitAndOverflowRenderers(int childPos, int layoutStatu
212212
metChildRenderer = metChildRenderer || isSplitLine;
213213

214214
// If the renderer to split is in the current line
215-
if (isSplitLine && !forcedPlacement && layoutStatus == LayoutResult.PARTIAL) {
215+
if (isSplitLine && !forcedPlacement && layoutStatus == LayoutResult.PARTIAL &&
216+
!FlexUtil.isColumnDirection(this)) {
216217
// It has sense to call it also for LayoutResult.NOTHING. And then try to layout remaining renderers
217218
// in line inside fillSplitOverflowRenderersForPartialResult to see if some of them can be left or
218219
// partially left on the first page (in split renderer). But it's not that easy.
219220
// So currently, if the 1st not fully layouted renderer is layouted with LayoutResult.NOTHING,
220221
// the whole line is moved to the next page (overflow renderer).
221-
fillSplitOverflowRenderersForPartialResult(splitRenderer, overflowRenderer, line, childRenderer,
222-
childResult);
222+
fillSplitOverflowRenderersForPartialResult(splitRenderer, overflowRenderer, line, childRenderer,
223+
childResult);
223224
getFlexItemMainDirector().applyDirectionForLine(overflowRenderer.getChildRenderers());
224225
} else {
225226
List<IRenderer> overflowRendererChildren = new ArrayList<IRenderer>();
@@ -339,6 +340,15 @@ MarginsCollapseInfo startChildMarginsHandling(IRenderer childRenderer,
339340

340341
@Override
341342
void decreaseLayoutBoxAfterChildPlacement(Rectangle layoutBox, LayoutResult result, IRenderer childRenderer) {
343+
if (FlexUtil.isColumnDirection(this)) {
344+
decreaseLayoutBoxAfterChildPlacementColumnLayout(layoutBox, childRenderer);
345+
} else {
346+
decreaseLayoutBoxAfterChildPlacementRowLayout(layoutBox,result, childRenderer);
347+
}
348+
}
349+
350+
void decreaseLayoutBoxAfterChildPlacementRowLayout(Rectangle layoutBox, LayoutResult result,
351+
IRenderer childRenderer) {
342352
layoutBox.decreaseWidth(result.getOccupiedArea().getBBox().getRight() - layoutBox.getLeft());
343353
layoutBox.setX(result.getOccupiedArea().getBBox().getRight());
344354

@@ -362,6 +372,28 @@ void decreaseLayoutBoxAfterChildPlacement(Rectangle layoutBox, LayoutResult resu
362372
}
363373
}
364374

375+
void decreaseLayoutBoxAfterChildPlacementColumnLayout(Rectangle layoutBox, IRenderer childRenderer) {
376+
FlexItemInfo childFlexItemInfo = findFlexItemInfo((AbstractRenderer) childRenderer);
377+
layoutBox.decreaseHeight(childFlexItemInfo.getRenderer().getOccupiedArea().getBBox().getHeight() +
378+
childFlexItemInfo.getRectangle().getY());
379+
380+
List<FlexItemInfo> line = findLine(childRenderer);
381+
final boolean isLastInLine = childRenderer.equals(line.get(line.size() - 1).getRenderer());
382+
// If it was the last renderer in line we have to go to the next line (row)
383+
if (isLastInLine) {
384+
float maxWidth = 0;
385+
float commonHeight = 0;
386+
for (FlexItemInfo item : line) {
387+
maxWidth = Math.max(maxWidth, item.getRenderer().getOccupiedArea().getBBox().getWidth()
388+
+ item.getRectangle().getX());
389+
commonHeight += item.getRectangle().getY() + item.getRenderer().getOccupiedArea().getBBox().getHeight();
390+
}
391+
layoutBox.increaseHeight(commonHeight);
392+
layoutBox.decreaseWidth(maxWidth);
393+
layoutBox.moveRight(maxWidth);
394+
}
395+
}
396+
365397
@Override
366398
Rectangle recalculateLayoutBoxBeforeChildLayout(Rectangle layoutBox,
367399
IRenderer childRenderer, Rectangle initialLayoutBox) {
@@ -459,8 +491,8 @@ private static void addSimulateDiv(AbstractRenderer overflowRenderer, float widt
459491
}
460492

461493
private void fillSplitOverflowRenderersForPartialResult(AbstractRenderer splitRenderer,
462-
AbstractRenderer overflowRenderer, List<FlexItemInfo> line, IRenderer childRenderer,
463-
LayoutResult childResult) {
494+
AbstractRenderer overflowRenderer, List<FlexItemInfo> line, IRenderer childRenderer,
495+
LayoutResult childResult) {
464496
float occupiedSpace = 0;
465497
float maxHeightInLine = 0;
466498
boolean metChildRendererInLine = false;
@@ -562,8 +594,13 @@ private void findMinMaxWidth(float initialMinWidth, float initialMaxWidth, Abstr
562594
} else {
563595
childMinMaxWidth = MinMaxWidthUtils.countDefaultMinMaxWidth(childRenderer);
564596
}
565-
maxWidth += childMinMaxWidth.getMaxWidth();
566-
minWidth += childMinMaxWidth.getMinWidth();
597+
if (FlexUtil.isColumnDirection(this)) {
598+
maxWidth = Math.max(maxWidth, childMinMaxWidth.getMaxWidth());
599+
minWidth = Math.max(minWidth, childMinMaxWidth.getMinWidth());
600+
} else {
601+
maxWidth += childMinMaxWidth.getMaxWidth();
602+
minWidth += childMinMaxWidth.getMinWidth();
603+
}
567604
}
568605
minMaxWidthHandler.updateMaxChildWidth(maxWidth);
569606
minMaxWidthHandler.updateMinChildWidth(minWidth);
@@ -579,10 +616,16 @@ private boolean isRowReverse() {
579616
this.<FlexDirectionPropertyValue>getProperty(Property.FLEX_DIRECTION, null);
580617
}
581618

619+
private boolean isColumnReverse() {
620+
return FlexDirectionPropertyValue.COLUMN_REVERSE ==
621+
this.<FlexDirectionPropertyValue>getProperty(Property.FLEX_DIRECTION, null);
622+
}
623+
582624
private IFlexItemMainDirector createMainDirector() {
583-
if (FlexDirectionPropertyValue.COLUMN ==
584-
this.<FlexDirectionPropertyValue>getProperty(Property.FLEX_DIRECTION)) {
585-
return new TopToBottomFlexItemMainDirector();
625+
if (FlexUtil.isColumnDirection(this)) {
626+
return isColumnReverse()
627+
? (IFlexItemMainDirector) new BottomToTopFlexItemMainDirector() :
628+
new TopToBottomFlexItemMainDirector();
586629
} else {
587630
final boolean isRtlDirection = BaseDirection.RIGHT_TO_LEFT ==
588631
this.<BaseDirection>getProperty(Property.BASE_DIRECTION, null);

0 commit comments

Comments
 (0)