Skip to content

Commit a1afcb7

Browse files
author
Fedorov Alexandr
committed
Fix align content workflow
DEVSIX-9178
1 parent 0927387 commit a1afcb7

File tree

5 files changed

+264
-72
lines changed

5 files changed

+264
-72
lines changed

layout/src/main/java/com/itextpdf/layout/properties/AlignContentPropertyValue.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ public enum AlignContentPropertyValue {
2727
CENTER,
2828
FLEX_START,
2929
FLEX_END,
30+
END,
31+
START,
3032
STRETCH,
3133
SPACE_BETWEEN,
3234
SPACE_AROUND,

layout/src/main/java/com/itextpdf/layout/properties/Property.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ public final class Property {
8484
public static final int FLEX_SHRINK = 127;
8585
public static final int FLEX_WRAP = 128;
8686
public static final int FLEX_DIRECTION = 139;
87+
public static final int FLEX_FORCE_START_ON_TOP = 158;
8788

8889
public static final int FLOAT = 99;
8990
public static final int FLUSH_ON_DRAW = 19;

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

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -535,7 +535,7 @@ private void fillSplitOverflowRenderersForPartialResult(AbstractRenderer splitRe
535535
// Get rid of vertical alignment for item with partial result. For column direction, justify-content
536536
// is applied to the entire line, not the single item, so there is no point in getting rid of it
537537
if (!FlexUtil.isColumnDirection(this)) {
538-
setAlignSelfIfNotStretch(childResult.getOverflowRenderer());
538+
startContentOnTopOfNewPage(childResult.getOverflowRenderer(), overflowRenderer);
539539
}
540540
overflowRenderer.addChildRenderer(childResult.getOverflowRenderer());
541541
}
@@ -575,7 +575,7 @@ private void fillSplitOverflowRenderersForPartialResult(AbstractRenderer splitRe
575575
if (neighbourLayoutResult.getOverflowRenderer() != null) {
576576
if (neighbourLayoutResult.getStatus() == LayoutResult.PARTIAL) {
577577
// Get rid of cross alignment for item with partial result
578-
setAlignSelfIfNotStretch(neighbourLayoutResult.getOverflowRenderer());
578+
startContentOnTopOfNewPage(neighbourLayoutResult.getOverflowRenderer(), overflowRenderer);
579579
}
580580
overflowRenderer.addChildRenderer(neighbourLayoutResult.getOverflowRenderer());
581581
} else {
@@ -600,16 +600,17 @@ private void fillSplitOverflowRenderersForPartialResult(AbstractRenderer splitRe
600600
}
601601
}
602602

603-
private void setAlignSelfIfNotStretch(IRenderer overflowRenderer) {
603+
private void startContentOnTopOfNewPage(IRenderer overflowChildRenderer, AbstractRenderer overflowRenderer) {
604604
AlignmentPropertyValue alignItems =
605605
(AlignmentPropertyValue) this.<AlignmentPropertyValue>getProperty(
606606
Property.ALIGN_ITEMS, AlignmentPropertyValue.STRETCH);
607607
AlignmentPropertyValue alignSelf =
608-
(AlignmentPropertyValue) overflowRenderer.<AlignmentPropertyValue>getProperty(
608+
(AlignmentPropertyValue) overflowChildRenderer.<AlignmentPropertyValue>getProperty(
609609
Property.ALIGN_SELF, alignItems);
610610
if (alignSelf != AlignmentPropertyValue.STRETCH) {
611-
overflowRenderer.setProperty(Property.ALIGN_SELF, AlignmentPropertyValue.START);
611+
overflowChildRenderer.setProperty(Property.ALIGN_SELF, AlignmentPropertyValue.START);
612612
}
613+
overflowRenderer.setProperty(Property.FLEX_FORCE_START_ON_TOP, true);
613614
}
614615

615616
private void restoreHeightForOverflowRenderer(IRenderer childRenderer, IRenderer overflowRenderer) {
@@ -701,6 +702,10 @@ private IFlexItemMainDirector createMainDirector() {
701702
private List<IRenderer> retrieveRenderersToOverflow(Rectangle flexContainerBBox) {
702703
List<IRenderer> renderersToOverflow = new ArrayList<>();
703704
Rectangle layoutContextRectangle = flexContainerBBox.clone();
705+
UnitValue unitWidthValue = (UnitValue) this.modelElement.<UnitValue>getProperty(Property.WIDTH);
706+
if (unitWidthValue != null && unitWidthValue.getValue() < layoutContextRectangle.getWidth()){
707+
layoutContextRectangle.setWidth(unitWidthValue.getValue());
708+
}
704709
applyMarginsBordersPaddings(layoutContextRectangle, false);
705710
if (FlexUtil.isColumnDirection(this) &&
706711
FlexUtil.getMainSize(this, layoutContextRectangle) >= layoutContextRectangle.getHeight()) {

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

Lines changed: 80 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,9 @@ public static List<List<FlexItemInfo>> calculateChildrenRectangles(Rectangle fle
8888
// We need to have crossSize only if its value is definite.
8989
Float[] crossSizes = getCrossSizes(flexContainerRenderer, layoutBox);
9090
Float crossSize = crossSizes[0];
91+
if (crossSize == null && isColumnDirection(flexContainerRenderer)) {
92+
crossSize = layoutBox.getWidth();
93+
}
9194
Float minCrossSize = crossSizes[1];
9295
Float maxCrossSize = crossSizes[2];
9396

@@ -194,27 +197,44 @@ private static void applyAlignContent(List<List<FlexItemCalculationInfo>> lines,
194197
AlignContentPropertyValue alignContent = (AlignContentPropertyValue) renderer
195198
.<AlignContentPropertyValue>getProperty(Property.ALIGN_CONTENT, AlignContentPropertyValue.NORMAL);
196199

200+
boolean isFirstFlexStart = (boolean) renderer.<Boolean>getProperty(Property.FLEX_FORCE_START_ON_TOP, false);
201+
197202
if (crossSize != null) {
198203
if (renderer.isWrapReverse()) {
199204
Collections.reverse(lines);
200205
}
201206

202-
float lineCrossSize = 0;
203-
204-
for (List<FlexItemCalculationInfo> line : lines) {
205-
float maxItemSize = getItemMaxCrossSize(line);
206-
lineCrossSize += maxItemSize;
207-
}
208-
207+
float boxSize;
209208
float freeSpace;
210209

211210
if (isColumnDirection(renderer)) {
212-
freeSpace = Math.min(layoutBox.getWidth(), (float) crossSize) - lineCrossSize;
211+
boxSize = Math.min(layoutBox.getWidth(), (float) crossSize);
213212
} else {
214-
freeSpace = Math.min(layoutBox.getHeight(), (float) crossSize) - lineCrossSize;
213+
boxSize = Math.min(layoutBox.getHeight(), (float) crossSize);
214+
}
215+
216+
float lineCrossSize = 0;
217+
int columnsOnPage = 0;
218+
219+
for (List<FlexItemCalculationInfo> line : lines) {
220+
float maxItemSize = getItemMaxCrossSize(line);
221+
if (isColumnDirection(renderer)) {
222+
if (lineCrossSize + maxItemSize <= boxSize) {
223+
lineCrossSize += maxItemSize;
224+
columnsOnPage++;
225+
} else {
226+
break;
227+
}
228+
} else {
229+
lineCrossSize += maxItemSize;
230+
}
215231
}
216232

217-
applyAlignContent(lines, alignContent, freeSpace, isColumnDirection(renderer));
233+
freeSpace = boxSize - lineCrossSize;
234+
applyAlignContent(lines, isColumnDirection(renderer) ? columnsOnPage : lines.size(),
235+
alignContent, freeSpace < 0 ? 0 : freeSpace,
236+
isColumnDirection(renderer),
237+
isFirstFlexStart);
218238

219239
if (renderer.isWrapReverse()) {
220240
Collections.reverse(lines);
@@ -223,36 +243,43 @@ private static void applyAlignContent(List<List<FlexItemCalculationInfo>> lines,
223243
}
224244

225245
private static void applyAlignContent(List<List<FlexItemCalculationInfo>> lines,
226-
AlignContentPropertyValue alignContent,
227-
float freeSpace, boolean isColumnDirection) {
246+
int linesOnPage, AlignContentPropertyValue alignContent,
247+
float freeSpace, boolean isColumnDirection, boolean isFirstFlexStart) {
228248
if (!lines.isEmpty()) {
229249
switch (alignContent) {
230250
case CENTER:
231-
applyCentralAlignment(lines, freeSpace, isColumnDirection);
251+
applyCenterAlignment(lines, freeSpace, isColumnDirection, isFirstFlexStart);
232252
break;
233253
case FLEX_END:
234-
applyFlexEndAlignment(lines, freeSpace, isColumnDirection);
254+
case END:
255+
applyFlexEndAlignment(lines, freeSpace, isColumnDirection, isFirstFlexStart);
235256
break;
236257
case SPACE_BETWEEN:
237-
applySpaceBetweenAlignment(lines, freeSpace, isColumnDirection);
258+
applySpaceBetweenAlignment(lines, linesOnPage, freeSpace, isColumnDirection);
238259
break;
239260
case SPACE_AROUND:
240-
applySpaceAroundAlignment(lines, freeSpace, isColumnDirection);
261+
applySpaceAroundAlignment(lines, linesOnPage, freeSpace, isColumnDirection, isFirstFlexStart);
241262
break;
242263
case SPACE_EVENLY:
243-
applySpaceEvenlyAlignment(lines, freeSpace, isColumnDirection);
264+
applySpaceEvenlyAlignment(lines, linesOnPage, freeSpace, isColumnDirection, isFirstFlexStart);
244265
break;
245266
case FLEX_START:
267+
case START:
268+
246269
default:
247270
break;
248-
// We don't need to do anything in these cases
271+
// We don't need to do anything in these cases
249272
}
250273
}
251274
}
252275

253276
private static void applyFlexEndAlignment(List<List<FlexItemCalculationInfo>> lines, float freeSpace,
254-
boolean isColumnDirection) {
255-
for (FlexItemCalculationInfo item : lines.get(0)) {
277+
boolean isColumnDirection, boolean isFirstFlexStart) {
278+
if (isFirstFlexStart && lines.size() < 2) {
279+
return;
280+
}
281+
List<FlexItemCalculationInfo> targetLine = isFirstFlexStart && lines.size() > 1 ? lines.get(1) : lines.get(0);
282+
for (FlexItemCalculationInfo item : targetLine) {
256283
if (isColumnDirection) {
257284
item.xShift = freeSpace;
258285
} else {
@@ -261,11 +288,12 @@ private static void applyFlexEndAlignment(List<List<FlexItemCalculationInfo>> li
261288
}
262289
}
263290

264-
private static void applySpaceBetweenAlignment(List<List<FlexItemCalculationInfo>> lines, float freeSpace,
291+
private static void applySpaceBetweenAlignment(List<List<FlexItemCalculationInfo>> lines, int linesOnPage,
292+
float freeSpace,
265293
boolean isColumnDirection) {
266-
if(lines.size() != 1) {
267-
float indentation = freeSpace / (lines.size() - 1);
268-
for (int i = 1; i < lines.size(); i++) {
294+
if (linesOnPage > 1) {
295+
final float indentation = freeSpace / (linesOnPage - 1);
296+
for (int i = 1; i < linesOnPage; i++) {
269297
for (FlexItemCalculationInfo item : lines.get(i)) {
270298
if (isColumnDirection) {
271299
item.xShift = indentation;
@@ -277,12 +305,12 @@ private static void applySpaceBetweenAlignment(List<List<FlexItemCalculationInfo
277305
}
278306
}
279307

280-
private static void applySpaceEvenlyAlignment(List<List<FlexItemCalculationInfo>> lines, float freeSpace,
281-
boolean isColumnDirection) {
282-
float indentation = freeSpace / (lines.size() + 1);
283-
284-
for (List<FlexItemCalculationInfo> line : lines) {
285-
for (FlexItemCalculationInfo item : line) {
308+
private static void applySpaceEvenlyAlignment(List<List<FlexItemCalculationInfo>> lines, int linesOnPage,
309+
float freeSpace, boolean isColumnDirection, boolean isFirstFlexStart) {
310+
final float indentation = freeSpace / (linesOnPage + 1);
311+
final int startIndex = isFirstFlexStart ? 1 : 0;
312+
for (int i = startIndex; i < linesOnPage; i++) {
313+
for (FlexItemCalculationInfo item : lines.get(i)) {
286314
if (isColumnDirection) {
287315
item.xShift = indentation;
288316
} else {
@@ -292,40 +320,36 @@ private static void applySpaceEvenlyAlignment(List<List<FlexItemCalculationInfo>
292320
}
293321
}
294322

295-
private static void applySpaceAroundAlignment(List<List<FlexItemCalculationInfo>> lines, float freeSpace,
296-
boolean isColumnDirection) {
297-
float indentation = freeSpace / lines.size();
298-
299-
for (FlexItemCalculationInfo item : lines.get(0)) {
300-
if (isColumnDirection) {
301-
item.xShift = indentation / 2;
302-
} else {
303-
item.yShift = indentation / 2;
304-
}
305-
}
306-
307-
if(lines.size() != 1) {
308-
for (int i = 1; i < lines.size(); i++) {
309-
for (FlexItemCalculationInfo item : lines.get(i)) {
310-
if (isColumnDirection) {
311-
item.xShift = indentation;
312-
} else {
313-
item.yShift = indentation;
314-
}
323+
private static void applySpaceAroundAlignment(List<List<FlexItemCalculationInfo>> lines, int linesOnPage,
324+
float freeSpace,
325+
boolean isColumnDirection, boolean isFirstFlexStart) {
326+
final int startIndex = isFirstFlexStart ? 1 : 0;
327+
final float indentation = freeSpace / linesOnPage;
328+
for (int i = startIndex; i < linesOnPage; i++) {
329+
float shift = (i == 0) ? (indentation / 2) : indentation;
330+
for (FlexItemCalculationInfo item : lines.get(i)) {
331+
if (isColumnDirection) {
332+
item.xShift = shift;
333+
} else {
334+
item.yShift = shift;
315335
}
316336
}
317337
}
318338
}
319339

320-
private static void applyCentralAlignment(List<List<FlexItemCalculationInfo>> lines, float freeSpace,
321-
boolean isColumnDirection) {
322-
for (FlexItemCalculationInfo item : lines.get(0)) {
340+
private static void applyCenterAlignment(List<List<FlexItemCalculationInfo>> lines, float freeSpace,
341+
boolean isColumnDirection, boolean isFirstFlexStart) {
342+
if (isFirstFlexStart && lines.size() < 2) {
343+
return;
344+
}
345+
final float indentation = freeSpace / 2;
346+
final int targetIndex = isFirstFlexStart && lines.size() > 1 ? 1 : 0;
347+
for (FlexItemCalculationInfo item : lines.get(targetIndex)) {
323348
if (isColumnDirection) {
324-
item.xShift = freeSpace / 2;
349+
item.xShift = indentation;
325350
} else {
326-
item.yShift = freeSpace / 2;
351+
item.yShift = indentation;
327352
}
328-
329353
}
330354
}
331355

0 commit comments

Comments
 (0)