Skip to content

Commit 0a68cf5

Browse files
committed
Basic Height width implementation + PDFIpsium generator
DEVSIX-7588
1 parent 9e78dab commit 0a68cf5

File tree

81 files changed

+932
-89
lines changed

Some content is hidden

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

81 files changed

+932
-89
lines changed

commons/src/main/java/com/itextpdf/commons/utils/PlaceHolderTextUtil.java

Lines changed: 529 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package com.itextpdf.commons.utils;
2+
3+
import com.itextpdf.commons.utils.PlaceHolderTextUtil.PlaceHolderTextBy;
4+
import com.itextpdf.test.ExtendedITextTest;
5+
import com.itextpdf.test.annotations.type.UnitTest;
6+
7+
import org.junit.Test;
8+
import org.junit.experimental.categories.Category;
9+
import static org.junit.Assert.assertEquals;
10+
import static org.junit.Assert.assertTrue;
11+
12+
13+
@Category(UnitTest.class)
14+
public class PlaceHolderTextUtilTest extends ExtendedITextTest {
15+
16+
@Test
17+
public void GetPlaceHolderByCharacterTextSimple() {
18+
int amountOfCharacters = 24;
19+
String result = PlaceHolderTextUtil.getPlaceHolderText(PlaceHolderTextBy.CHARACTERS, amountOfCharacters);
20+
assertEquals(amountOfCharacters, result.length());
21+
assertEquals(result, "Portable Document Format");
22+
}
23+
24+
25+
@Test
26+
public void GetPlaceHolderByCharactersTextOverflow() {
27+
int amountOfCharacters = 31222 + 24;
28+
String result = PlaceHolderTextUtil.getPlaceHolderText(PlaceHolderTextBy.CHARACTERS, amountOfCharacters);
29+
assertEquals(amountOfCharacters, result.length());
30+
assertTrue(result.endsWith("Portable Document Format"));
31+
}
32+
33+
@Test
34+
public void GetPlaceHolderByWordsTextSimple() {
35+
int amountOfWords = 5;
36+
String result = PlaceHolderTextUtil.getPlaceHolderText(PlaceHolderTextBy.WORDS, amountOfWords);
37+
assertEquals(44, result.length());
38+
}
39+
40+
41+
@Test
42+
public void GetPlaceHolderByWordsTextOverflow() {
43+
int amountOfCharacters = 4000;
44+
String result = PlaceHolderTextUtil.getPlaceHolderText(PlaceHolderTextBy.WORDS, amountOfCharacters);
45+
assertEquals(25472, result.length());
46+
}
47+
48+
}

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

Lines changed: 77 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ public class MulticolRenderer extends AbstractRenderer {
4646
private int columnCount;
4747
private float columnWidth;
4848
private float approximateHeight;
49+
private Float heightFromProperties;
4950

5051
/**
5152
* Creates a DivRenderer from its corresponding layout object.
@@ -72,11 +73,14 @@ public final void setHeightCalculator(ColumnHeightCalculator heightCalculator) {
7273
@Override
7374
public LayoutResult layout(LayoutContext layoutContext) {
7475
this.setProperty(Property.TREAT_AS_CONTINUOUS_CONTAINER, Boolean.TRUE);
75-
final Rectangle actualBBox = layoutContext.getArea().getBBox().clone();
76+
77+
Rectangle actualBBox = layoutContext.getArea().getBBox().clone();
78+
float originalWidth = actualBBox.getWidth();
79+
applyWidth(actualBBox, originalWidth);
7680
applyPaddings(actualBBox, false);
7781
applyBorderBox(actualBBox, false);
7882
applyMargins(actualBBox, false);
79-
83+
heightFromProperties = determineHeight(actualBBox);
8084
columnCount = (int) this.<Integer>getProperty(Property.COLUMN_COUNT);
8185
columnWidth = actualBBox.getWidth() / columnCount;
8286
if (this.elementRenderer == null) {
@@ -164,6 +168,45 @@ protected AbstractRenderer createOverflowRenderer(IRenderer overflowedContentRen
164168
return overflowRenderer;
165169
}
166170

171+
private void applyWidth(Rectangle parentBbox, float originalWidth) {
172+
final Float blockWidth = retrieveWidth(originalWidth);
173+
if (blockWidth != null) {
174+
parentBbox.setWidth((float) blockWidth);
175+
} else {
176+
final Float minWidth = retrieveMinWidth(parentBbox.getWidth());
177+
if (minWidth != null && minWidth > parentBbox.getWidth()) {
178+
parentBbox.setWidth((float) minWidth);
179+
}
180+
}
181+
}
182+
183+
private Float determineHeight(Rectangle parentBBox) {
184+
Float height = retrieveHeight();
185+
final Float minHeight = retrieveMinHeight();
186+
final Float maxHeight = retrieveMaxHeight();
187+
if (height == null || (minHeight != null && height < minHeight)) {
188+
if ((minHeight != null) && parentBBox.getHeight() < minHeight) {
189+
height = minHeight;
190+
}
191+
}
192+
if (height != null && maxHeight != null && height > maxHeight) {
193+
height = maxHeight;
194+
}
195+
return height;
196+
}
197+
198+
199+
private void recalculateHeightWidthAfterLayouting(Rectangle parentBBox) {
200+
Float height = determineHeight(parentBBox);
201+
if (height != null) {
202+
float heightDelta = parentBBox.getHeight() - (float) height;
203+
parentBBox.moveUp(heightDelta);
204+
parentBBox.setHeight((float) height);
205+
}
206+
applyWidth(parentBBox, parentBBox.getWidth());
207+
}
208+
209+
167210
private float safelyRetrieveFloatProperty(int property) {
168211
final Object value = this.<Object>getProperty(property);
169212
if (value instanceof UnitValue) {
@@ -187,19 +230,44 @@ private MulticolLayoutResult balanceContentAndLayoutColumns(LayoutContext prelay
187230
isLastLayout = true;
188231
approximateHeight = maxHeight;
189232
}
190-
result = layoutColumnsAndReturnOverflowRenderer(prelayoutContext, actualBbox);
233+
// height calcultion
234+
float workingHeight = approximateHeight;
235+
if (heightFromProperties != null) {
236+
workingHeight = Math.min((float) heightFromProperties, (float) approximateHeight);
237+
workingHeight -= safelyRetrieveFloatProperty(Property.PADDING_TOP);
238+
workingHeight -= safelyRetrieveFloatProperty(Property.PADDING_BOTTOM);
239+
workingHeight -= safelyRetrieveFloatProperty(Property.BORDER_TOP);
240+
workingHeight -= safelyRetrieveFloatProperty(Property.BORDER_BOTTOM);
241+
workingHeight -= safelyRetrieveFloatProperty(Property.BORDER) * 2;
242+
workingHeight -= safelyRetrieveFloatProperty(Property.MARGIN_TOP);
243+
workingHeight -= safelyRetrieveFloatProperty(Property.MARGIN_BOTTOM);
244+
}
245+
result = layoutColumnsAndReturnOverflowRenderer(prelayoutContext, actualBbox, workingHeight);
246+
191247
if (result.getOverflowRenderer() == null || isLastLayout) {
248+
clearOverFlowRendererIfNeeded(result);
192249
return result;
193250
}
194251
additionalHeightPerIteration = heightCalculator.getAdditionalHeightOfEachColumn(this, result).floatValue();
195252
if (Math.abs(additionalHeightPerIteration) <= ZERO_DELTA) {
253+
clearOverFlowRendererIfNeeded(result);
196254
return result;
197255
}
198256
approximateHeight += additionalHeightPerIteration;
257+
clearOverFlowRendererIfNeeded(result);
199258
}
200259
return result;
201260
}
202261

262+
private void clearOverFlowRendererIfNeeded(MulticolLayoutResult result) {
263+
//When we have a height set on the element but the content doesn't fit in the given height
264+
//we don't want to render the overflow renderer as it would be rendered in the next area
265+
if (heightFromProperties != null && heightFromProperties < approximateHeight) {
266+
result.setOverflowRenderer(null);
267+
}
268+
}
269+
270+
203271
private LayoutArea calculateContainerOccupiedArea(LayoutContext layoutContext, boolean isFull) {
204272
LayoutArea area = layoutContext.getArea().clone();
205273
float totalHeight = approximateHeight;
@@ -221,6 +289,7 @@ private LayoutArea calculateContainerOccupiedArea(LayoutContext layoutContext, b
221289
area.getBBox().setHeight(totalHeight);
222290
final Rectangle initialBBox = layoutContext.getArea().getBBox();
223291
area.getBBox().setY(initialBBox.getY() + initialBBox.getHeight() - area.getBBox().getHeight());
292+
recalculateHeightWidthAfterLayouting(area.getBBox());
224293
return area;
225294
}
226295

@@ -232,16 +301,16 @@ private BlockRenderer getElementsRenderer() {
232301
}
233302

234303
private MulticolLayoutResult layoutColumnsAndReturnOverflowRenderer(LayoutContext preLayoutContext,
235-
Rectangle actualBBox) {
304+
Rectangle actualBBox, float workingHeight) {
236305
MulticolLayoutResult result = new MulticolLayoutResult();
237306
IRenderer renderer = elementRenderer;
307+
238308
for (int i = 0; i < columnCount && renderer != null; i++) {
239309
LayoutArea tempArea = preLayoutContext.getArea().clone();
240310
tempArea.getBBox().setWidth(columnWidth);
241-
tempArea.getBBox().setHeight(approximateHeight);
311+
tempArea.getBBox().setHeight(workingHeight);
242312
tempArea.getBBox().setX(actualBBox.getX() + columnWidth * i);
243-
tempArea.getBBox().setY(actualBBox.getY() + actualBBox.getHeight() - tempArea.getBBox()
244-
.getHeight());
313+
tempArea.getBBox().setY(actualBBox.getY() + actualBBox.getHeight() - tempArea.getBBox().getHeight());
245314

246315
LayoutContext columnContext = new LayoutContext(tempArea, preLayoutContext.getMarginsCollapseInfo(),
247316
preLayoutContext.getFloatRendererAreas(), preLayoutContext.isClippedHeight());
@@ -252,6 +321,7 @@ private MulticolLayoutResult layoutColumnsAndReturnOverflowRenderer(LayoutContex
252321
result.setCauseOfNothing(tempResultColumn.getCauseOfNothing());
253322
return result;
254323
}
324+
255325
if (tempResultColumn.getSplitRenderer() == null) {
256326
result.getSplitRenderers().add(renderer);
257327
} else {

0 commit comments

Comments
 (0)