Skip to content

Commit 79b8115

Browse files
committed
Initial overflow support
If block container has overflow property, iText will use its width and height despite it might be bigger than parent's. If direct parent container has overflow property, iText will process Text and Image elements as if there is enough space for them. Clip and path area in draw() to perform HIDDEN overflow DEVSIX-992 Autoported commit. Original commit hash: [fc607f8]
1 parent 81c4b42 commit 79b8115

File tree

15 files changed

+230
-34
lines changed

15 files changed

+230
-34
lines changed

itext.tests/itext.layout.tests/itext/layout/TextWritingTest.cs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,45 @@ public virtual void FontStyleSimulationTest01() {
250250
, "diff"));
251251
}
252252

253+
/// <exception cref="System.IO.IOException"/>
254+
/// <exception cref="System.Exception"/>
255+
[NUnit.Framework.Test]
256+
public virtual void BigWordTest01() {
257+
String outFileName = destinationFolder + "bigWordTest01.pdf";
258+
String cmpFileName = sourceFolder + "cmp_bigWordTest01.pdf";
259+
PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outFileName));
260+
Document doc = new Document(pdfDoc);
261+
Paragraph p = new Paragraph();
262+
p.SetWidth(150);
263+
p.SetBackgroundColor(Color.RED);
264+
p.Add("Hello ho ho ho ");
265+
p.Add("LongWordThatDoNotFitInALine");
266+
p.SetProperty(Property.OVERFLOW_X, OverflowPropertyValue.VISIBLE);
267+
doc.Add(p);
268+
p = new Paragraph();
269+
p.SetWidth(150);
270+
p.SetBackgroundColor(Color.RED);
271+
p.Add("LongWordThatDoNotFitInALine World");
272+
p.SetProperty(Property.OVERFLOW_X, OverflowPropertyValue.VISIBLE);
273+
doc.Add(p);
274+
p = new Paragraph();
275+
p.SetWidth(150);
276+
p.SetBackgroundColor(Color.RED);
277+
p.Add("World LongWordThatDoNotFitInALine");
278+
p.SetProperty(Property.OVERFLOW_X, OverflowPropertyValue.VISIBLE);
279+
doc.Add(p);
280+
p = new Paragraph();
281+
p.SetWidth(150);
282+
p.SetBackgroundColor(Color.RED);
283+
p.Add("World ");
284+
p.Add("LongWordThatDoNotFitInALine");
285+
p.SetProperty(Property.OVERFLOW_X, OverflowPropertyValue.VISIBLE);
286+
doc.Add(p);
287+
doc.Close();
288+
NUnit.Framework.Assert.IsNull(new CompareTool().CompareByContent(outFileName, cmpFileName, destinationFolder
289+
, "diff"));
290+
}
291+
253292
/// <exception cref="System.IO.IOException"/>
254293
/// <exception cref="System.Exception"/>
255294
[NUnit.Framework.Test]
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

itext/itext.layout/itext/layout/element/BlockElement.cs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,20 @@ public abstract class BlockElement<T> : AbstractElement<T>, IAccessibleElement,
6262
protected internal BlockElement() {
6363
}
6464

65+
public override T1 GetDefaultProperty<T1>(int property) {
66+
switch (property) {
67+
case Property.OVERFLOW:
68+
case Property.OVERFLOW_X:
69+
case Property.OVERFLOW_Y: {
70+
return (T1)(Object)OverflowPropertyValue.FIT;
71+
}
72+
73+
default: {
74+
return base.GetDefaultProperty<T1>(property);
75+
}
76+
}
77+
}
78+
6579
/// <summary>Gets the current left margin width of the element.</summary>
6680
/// <returns>the left margin width, as a <code>float</code></returns>
6781
public virtual float? GetMarginLeft() {
@@ -339,6 +353,34 @@ public virtual T SetMinHeight(float minHeight) {
339353
return (T)(Object)this;
340354
}
341355

356+
/// <summary>Sets the overflow-x value.</summary>
357+
///
358+
/// <returns>this element</returns>
359+
public virtual T SetOverflowX(OverflowPropertyValue? overflow) {
360+
SetProperty(Property.OVERFLOW_X, overflow);
361+
return (T)(Object)this;
362+
}
363+
364+
/// <summary>Sets the overflow-y value.</summary>
365+
///
366+
/// <returns>this element</returns>
367+
public virtual T SetOverflowY(OverflowPropertyValue? overflow) {
368+
SetProperty(Property.OVERFLOW_Y, overflow);
369+
return (T)(Object)this;
370+
}
371+
372+
/// <summary>Gets the overflow-x value of the element.</summary>
373+
/// <returns>the overflow-x value of the element.</returns>
374+
public virtual OverflowPropertyValue? GetOverflowX() {
375+
return this.GetProperty<OverflowPropertyValue?>(Property.OVERFLOW_X);
376+
}
377+
378+
/// <summary>Gets the overflow-y value of the element.</summary>
379+
/// <returns>the overflow-y value of the element.</returns>
380+
public virtual OverflowPropertyValue? GetOverflowY() {
381+
return this.GetProperty<OverflowPropertyValue?>(Property.OVERFLOW_Y);
382+
}
383+
342384
public abstract AccessibilityProperties GetAccessibilityProperties();
343385

344386
public abstract PdfName GetRole();
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
namespace iText.Layout.Properties {
2+
public enum OverflowPropertyValue {
3+
FIT,
4+
VISIBLE,
5+
HIDDEN
6+
}
7+
}

itext/itext.layout/itext/layout/properties/Property.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,12 @@ private Property() {
218218

219219
public const int OPACITY = 92;
220220

221+
public const int OVERFLOW = 102;
222+
223+
public const int OVERFLOW_X = 103;
224+
225+
public const int OVERFLOW_Y = 104;
226+
221227
public const int PADDING_BOTTOM = 47;
222228

223229
public const int PADDING_LEFT = 48;

itext/itext.layout/itext/layout/renderer/BlockRenderer.cs

Lines changed: 55 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -102,25 +102,33 @@ public override LayoutResult Layout(LayoutContext layoutContext) {
102102
Border[] borders = GetBorders();
103103
float[] paddings = GetPaddings();
104104
ApplyBordersPaddingsMargins(parentBBox, borders, paddings);
105-
if (blockWidth != null && (blockWidth < parentBBox.GetWidth() || isPositioned || rotation != null)) {
105+
OverflowPropertyValue? overflowX = this.GetProperty<OverflowPropertyValue?>(Property.OVERFLOW_X);
106+
OverflowPropertyValue? overflowY = this.GetProperty<OverflowPropertyValue?>(Property.OVERFLOW_Y);
107+
if (blockWidth != null && (blockWidth < parentBBox.GetWidth() || isPositioned || rotation != null || (null
108+
!= overflowX && !OverflowPropertyValue.FIT.Equals(overflowX)))) {
106109
// TODO DEVSIX-1174
107110
UnitValue widthVal = this.GetProperty<UnitValue>(Property.WIDTH);
108-
if (widthVal != null && widthVal.IsPercentValue() && widthVal.GetValue() == 100) {
111+
if (widthVal != null && widthVal.IsPercentValue() && widthVal.GetValue() == 100 && (null == overflowX || OverflowPropertyValue
112+
.FIT.Equals(overflowX))) {
109113
}
110114
else {
111115
parentBBox.SetWidth((float)blockWidth);
112116
}
113117
}
114118
float? blockMaxHeight = RetrieveMaxHeight();
115-
if (!IsFixedLayout() && null != blockMaxHeight && blockMaxHeight < parentBBox.GetHeight() && !true.Equals(
116-
GetPropertyAsBoolean(Property.FORCED_PLACEMENT))) {
119+
if (!IsFixedLayout() && null != blockMaxHeight && (blockMaxHeight < parentBBox.GetHeight() || (null != overflowY
120+
&& !OverflowPropertyValue.FIT.Equals(overflowY))) && !true.Equals(GetPropertyAsBoolean(Property.FORCED_PLACEMENT
121+
))) {
122+
if (blockMaxHeight < parentBBox.GetHeight()) {
123+
wasHeightClipped = true;
124+
}
117125
float heightDelta = parentBBox.GetHeight() - (float)blockMaxHeight;
118126
if (marginsCollapsingEnabled && !isCellRenderer) {
119127
marginsCollapseHandler.ProcessFixedHeightAdjustment(heightDelta);
120128
}
121129
parentBBox.MoveUp(heightDelta).SetHeight((float)blockMaxHeight);
122-
wasHeightClipped = true;
123130
}
131+
Rectangle contentBoxToFit = parentBBox.Clone();
124132
IList<Rectangle> areas;
125133
if (isPositioned) {
126134
areas = JavaCollectionsUtil.SingletonList(parentBBox);
@@ -161,7 +169,7 @@ public override LayoutResult Layout(LayoutContext layoutContext) {
161169
else {
162170
if (result.GetOccupiedArea() != null && result.GetStatus() != LayoutResult.NOTHING) {
163171
occupiedArea.SetBBox(Rectangle.GetCommonRectangle(occupiedArea.GetBBox(), result.GetOccupiedArea().GetBBox
164-
()));
172+
()).SetWidth(occupiedArea.GetBBox().GetWidth()));
165173
}
166174
}
167175
if (FloatingHelper.IsRendererFloating(this) || isCellRenderer) {
@@ -321,7 +329,7 @@ public override LayoutResult Layout(LayoutContext layoutContext) {
321329
if (!FloatingHelper.IsRendererFloating(childRenderer)) {
322330
// this check is needed only if margins collapsing is enabled
323331
occupiedArea.SetBBox(Rectangle.GetCommonRectangle(occupiedArea.GetBBox(), result.GetOccupiedArea().GetBBox
324-
()));
332+
()).SetWidth(occupiedArea.GetBBox().GetWidth()));
325333
}
326334
}
327335
if (marginsCollapsingEnabled) {
@@ -359,8 +367,12 @@ public override LayoutResult Layout(LayoutContext layoutContext) {
359367
)blockMinHeight);
360368
}
361369
else {
362-
float blockBottom = Math.Max(occupiedArea.GetBBox().GetBottom() - ((float)blockMinHeight - occupiedArea.GetBBox
363-
().GetHeight()), layoutBox.GetBottom());
370+
float blockBottom = occupiedArea.GetBBox().GetBottom() - ((float)blockMinHeight - occupiedArea.GetBBox().GetHeight
371+
());
372+
if ((null == overflowY || OverflowPropertyValue.FIT.Equals(overflowY)) && blockBottom < layoutBox.GetBottom
373+
()) {
374+
blockBottom = layoutBox.GetBottom();
375+
}
364376
occupiedArea.GetBBox().IncreaseHeight(occupiedArea.GetBBox().GetBottom() - blockBottom).SetY(blockBottom);
365377
blockMinHeight -= occupiedArea.GetBBox().GetHeight();
366378
if (!IsFixedLayout() && blockMinHeight > AbstractRenderer.EPS) {
@@ -393,6 +405,7 @@ public override LayoutResult Layout(LayoutContext layoutContext) {
393405
if (isPositioned) {
394406
CorrectPositionedLayout(layoutBox);
395407
}
408+
float overflowPartHeight = GetOverflowPartHeight(overflowY, contentBoxToFit);
396409
ApplyPaddings(occupiedArea.GetBBox(), paddings, true);
397410
ApplyBorderBox(occupiedArea.GetBBox(), borders, true);
398411
ApplyMargins(occupiedArea.GetBBox(), true);
@@ -427,6 +440,9 @@ public override LayoutResult Layout(LayoutContext layoutContext) {
427440
}
428441
}
429442
}
443+
if (wasHeightClipped) {
444+
occupiedArea.GetBBox().MoveUp(overflowPartHeight).DecreaseHeight(overflowPartHeight);
445+
}
430446
if (null == overflowRenderer_1) {
431447
return new LayoutResult(LayoutResult.FULL, editedArea_1, null, null, causeOfNothing);
432448
}
@@ -497,8 +513,27 @@ public override void Draw(DrawContext drawContext) {
497513
BeginRotationIfApplied(drawContext.GetCanvas());
498514
DrawBackground(drawContext);
499515
DrawBorder(drawContext);
516+
OverflowPropertyValue? overflowX = this.GetProperty<OverflowPropertyValue?>(Property.OVERFLOW_X);
517+
OverflowPropertyValue? overflowY = this.GetProperty<OverflowPropertyValue?>(Property.OVERFLOW_Y);
518+
bool processOverflow = OverflowPropertyValue.HIDDEN.Equals(overflowX) || OverflowPropertyValue.HIDDEN.Equals
519+
(overflowY);
520+
if (processOverflow) {
521+
drawContext.GetCanvas().SaveState();
522+
Rectangle clippedArea = drawContext.GetDocument().GetPage(occupiedArea.GetPageNumber()).GetPageSize();
523+
Rectangle area = GetBorderAreaBBox();
524+
if (OverflowPropertyValue.HIDDEN.Equals(overflowX)) {
525+
clippedArea.SetX(area.GetX()).SetWidth(area.GetWidth());
526+
}
527+
if (OverflowPropertyValue.HIDDEN.Equals(overflowY)) {
528+
clippedArea.SetY(area.GetY()).SetHeight(area.GetHeight());
529+
}
530+
drawContext.GetCanvas().Rectangle(clippedArea).Clip().NewPath();
531+
}
500532
DrawChildren(drawContext);
501533
DrawPositionedChildren(drawContext);
534+
if (processOverflow) {
535+
drawContext.GetCanvas().RestoreState();
536+
}
502537
EndRotationIfApplied(drawContext.GetCanvas());
503538
EndElementOpacityApplying(drawContext);
504539
if (isRelativePosition) {
@@ -690,6 +725,17 @@ protected internal virtual void CorrectPositionedLayout(Rectangle layoutBox) {
690725
}
691726
}
692727

728+
protected internal virtual float GetOverflowPartHeight(OverflowPropertyValue? overflowY, Rectangle parentBox
729+
) {
730+
float difference = 0;
731+
if (null != overflowY && OverflowPropertyValue.FIT != overflowY) {
732+
if (occupiedArea.GetBBox().GetBottom() < parentBox.GetBottom()) {
733+
difference = parentBox.GetBottom() - occupiedArea.GetBBox().GetBottom();
734+
}
735+
}
736+
return difference;
737+
}
738+
693739
protected internal virtual float ApplyBordersPaddingsMargins(Rectangle parentBBox, Border[] borders, float
694740
[] paddings) {
695741
float parentWidth = parentBBox.GetWidth();

itext/itext.layout/itext/layout/renderer/FloatingHelper.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -228,9 +228,8 @@ internal static void RemoveFloatsAboveRendererBottom(IList<Rectangle> floatRende
228228
internal static LayoutArea AdjustResultOccupiedAreaForFloatAndClear(IRenderer renderer, IList<Rectangle> floatRendererAreas
229229
, Rectangle parentBBox, float clearHeightCorrection, bool marginsCollapsingEnabled) {
230230
LayoutArea occupiedArea = renderer.GetOccupiedArea();
231-
LayoutArea editedArea = occupiedArea;
231+
LayoutArea editedArea = occupiedArea.Clone();
232232
if (IsRendererFloating(renderer)) {
233-
editedArea = occupiedArea.Clone();
234233
if (occupiedArea.GetBBox().GetWidth() > 0) {
235234
floatRendererAreas.Add(occupiedArea.GetBBox());
236235
}
@@ -239,7 +238,6 @@ internal static LayoutArea AdjustResultOccupiedAreaForFloatAndClear(IRenderer re
239238
}
240239
else {
241240
if (clearHeightCorrection > 0 && !marginsCollapsingEnabled) {
242-
editedArea = occupiedArea.Clone();
243241
editedArea.GetBBox().IncreaseHeight(clearHeightCorrection);
244242
}
245243
}

0 commit comments

Comments
 (0)