Skip to content

Commit 572ba63

Browse files
LodrKumquatyulian-gaponenko
authored andcommitted
Support minMaxWidth counting for span- and special scripts wrapping
DEVSIX-3997 Autoported commit. Original commit hash: [dc43a8e1c4]
1 parent 8161b74 commit 572ba63

File tree

8 files changed

+388
-34
lines changed

8 files changed

+388
-34
lines changed

itext.tests/itext.layout.tests/itext/layout/renderer/LineRendererUnitTest.cs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,15 @@ source product.
4040
For more information, please contact iText Software Corp. at this
4141
4242
*/
43+
using System.IO;
4344
using iText.IO.Font.Constants;
4445
using iText.IO.Util;
4546
using iText.Kernel.Font;
4647
using iText.Kernel.Geom;
48+
using iText.Kernel.Pdf;
4749
using iText.Kernel.Pdf.Xobject;
4850
using iText.Layout;
51+
using iText.Layout.Borders;
4952
using iText.Layout.Element;
5053
using iText.Layout.Layout;
5154
using iText.Layout.Properties;
@@ -250,5 +253,31 @@ public virtual void LineRendererLayoutInHtmlModeWithLineHeightPropertyNotSet() {
250253
Rectangle bboxLineHeightNormal = layoutResLineHeightNormal.GetOccupiedArea().GetBBox();
251254
NUnit.Framework.Assert.IsTrue(bboxLineHeightNotSet.EqualsWithEpsilon(bboxLineHeightNormal));
252255
}
256+
257+
[NUnit.Framework.Test]
258+
public virtual void MinMaxWidthEqualsActualMarginsBordersPaddings() {
259+
PdfDocument pdfDocument = new PdfDocument(new PdfWriter(new MemoryStream()));
260+
Document document = new Document(pdfDocument);
261+
Text ranText = new Text("ran");
262+
ranText.SetProperty(Property.MARGIN_LEFT, new UnitValue(UnitValue.POINT, 8f));
263+
ranText.SetProperty(Property.MARGIN_RIGHT, new UnitValue(UnitValue.POINT, 10f));
264+
ranText.SetProperty(Property.BORDER_RIGHT, new SolidBorder(3));
265+
ranText.SetProperty(Property.PADDING_RIGHT, new UnitValue(UnitValue.POINT, 13f));
266+
TextRenderer ran = new TextRenderer(ranText);
267+
Text domText = new Text("dom");
268+
domText.SetProperty(Property.MARGIN_LEFT, new UnitValue(UnitValue.POINT, 17f));
269+
domText.SetProperty(Property.BORDER_LEFT, new SolidBorder(4));
270+
domText.SetProperty(Property.PADDING_LEFT, new UnitValue(UnitValue.POINT, 12f));
271+
domText.SetProperty(Property.MARGIN_RIGHT, new UnitValue(UnitValue.POINT, 2f));
272+
TextRenderer dom = new TextRenderer(domText);
273+
LayoutArea layoutArea = new LayoutArea(1, new Rectangle(AbstractRenderer.INF, AbstractRenderer.INF));
274+
LineRenderer lineRenderer = new LineRenderer();
275+
lineRenderer.SetParent(document.GetRenderer());
276+
lineRenderer.AddChild(ran);
277+
lineRenderer.AddChild(dom);
278+
float countedMinWidth = lineRenderer.GetMinMaxWidth().GetMinWidth();
279+
LayoutResult result = lineRenderer.Layout(new LayoutContext(layoutArea));
280+
NUnit.Framework.Assert.AreEqual(result.GetOccupiedArea().GetBBox().GetWidth(), countedMinWidth, 0.0001);
281+
}
253282
}
254283
}

itext.tests/itext.layout.tests/itext/layout/renderer/TextRendererIntegrationTest.cs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ You should have received a copy of the GNU Affero General Public License
3333
using iText.Layout.Element;
3434
using iText.Layout.Properties;
3535
using iText.Test;
36+
using iText.Test.Attributes;
3637

3738
namespace iText.Layout.Renderer {
3839
public class TextRendererIntegrationTest : ExtendedITextTest {
@@ -302,5 +303,34 @@ public virtual void WordSplitAcrossRenderersWithPrecedingImageRenderer() {
302303
NUnit.Framework.Assert.IsNull(new CompareTool().CompareByContent(outFileName, cmpFileName, destinationFolder
303304
));
304305
}
306+
307+
[NUnit.Framework.Test]
308+
[LogMessage(iText.IO.LogMessageConstant.TABLE_WIDTH_IS_MORE_THAN_EXPECTED_DUE_TO_MIN_WIDTH)]
309+
public virtual void MinMaxWidthWordSplitAcrossMultipleTextRenderers() {
310+
String outFileName = destinationFolder + "minMaxWidthWordSplitAcrossMultipleTextRenderers.pdf";
311+
String cmpFileName = sourceFolder + "cmp_minMaxWidthWordSplitAcrossMultipleTextRenderers.pdf";
312+
PdfDocument pdfDocument = new PdfDocument(new PdfWriter(outFileName));
313+
Document doc = new Document(pdfDocument);
314+
doc.SetFontSize(20);
315+
Text wissen = new Text("Wissen").SetFontColor(ColorConstants.PINK).SetBackgroundColor(ColorConstants.YELLOW
316+
);
317+
Text schaft = new Text("schaft").SetFontColor(ColorConstants.MAGENTA).SetBackgroundColor(ColorConstants.YELLOW
318+
);
319+
Text ler = new Text("ler is a long German word!").SetFontColor(ColorConstants.RED).SetBackgroundColor(ColorConstants
320+
.YELLOW);
321+
iText.Layout.Element.Image image = new iText.Layout.Element.Image(ImageDataFactory.Create(sourceFolder + "bulb.gif"
322+
));
323+
image.SetWidth(30);
324+
Paragraph text = new Paragraph().Add(wissen).Add(schaft).Add(ler);
325+
float[] colWidth = new float[] { 10, 20, 30, 40, 50 };
326+
Table table = new Table(UnitValue.CreatePercentArray(colWidth));
327+
for (int i = 0; i < colWidth.Length; i++) {
328+
table.AddCell(new Cell().Add(text));
329+
}
330+
doc.Add(table);
331+
doc.Close();
332+
NUnit.Framework.Assert.IsNull(new CompareTool().CompareByContent(outFileName, cmpFileName, destinationFolder
333+
));
334+
}
305335
}
306336
}

itext.tests/itext.layout.tests/itext/layout/renderer/WordWrapUnitTest.cs

Lines changed: 48 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -536,29 +536,46 @@ public virtual void NothingLayoutResult() {
536536
[NUnit.Framework.Test]
537537
public virtual void UpdateSpecialScriptLayoutResultsNonTextRenderer() {
538538
IDictionary<int, LayoutResult> specialScriptLayoutResults = new Dictionary<int, LayoutResult>();
539-
LayoutResult res = new LayoutResult(LayoutResult.NOTHING, new LayoutArea(0, new Rectangle(0, 0, 10, 10)),
540-
null, null);
541-
specialScriptLayoutResults.Put(-1, res);
539+
TextLayoutResult res = new TextLayoutResult(LayoutResult.NOTHING, new LayoutArea(0, new Rectangle(0, 0, 10
540+
, 10)), null, null, null);
541+
specialScriptLayoutResults.Put(0, res);
542542
NUnit.Framework.Assert.IsFalse(specialScriptLayoutResults.IsEmpty());
543543
TabRenderer tabRenderer = new TabRenderer(new Tab());
544-
LineRenderer.UpdateSpecialScriptLayoutResults(specialScriptLayoutResults, tabRenderer, 0, res);
544+
LineRenderer.MinMaxWidthOfTextRendererSequenceHelper minMaxWidthOfTextRendererSequenceHelper = new LineRenderer.MinMaxWidthOfTextRendererSequenceHelper
545+
(0f, 0f, false);
546+
AbstractWidthHandler widthHandler = new MaxSumWidthHandler(new MinMaxWidth());
547+
PdfDocument pdfDocument = new PdfDocument(new PdfWriter(new MemoryStream()));
548+
Document document = new Document(pdfDocument);
549+
LineRenderer lineRenderer = new LineRenderer();
550+
lineRenderer.SetParent(document.GetRenderer());
551+
lineRenderer.AddChild(tabRenderer);
552+
lineRenderer.UpdateSpecialScriptLayoutResults(specialScriptLayoutResults, tabRenderer, 1, res, minMaxWidthOfTextRendererSequenceHelper
553+
, false, widthHandler);
545554
NUnit.Framework.Assert.IsTrue(specialScriptLayoutResults.IsEmpty());
546555
}
547556

548557
[NUnit.Framework.Test]
549558
public virtual void UpdateSpecialScriptLayoutResultsFloatingRenderer() {
550559
IDictionary<int, LayoutResult> specialScriptLayoutResults = new Dictionary<int, LayoutResult>();
551-
LayoutResult res = new LayoutResult(LayoutResult.NOTHING, new LayoutArea(0, new Rectangle(0, 0, 10, 10)),
552-
null, null);
553-
int childPosToRemain = -1;
560+
TextLayoutResult res = new TextLayoutResult(LayoutResult.NOTHING, new LayoutArea(0, new Rectangle(0, 0, 10
561+
, 10)), null, null, null);
562+
int childPosToRemain = 0;
554563
specialScriptLayoutResults.Put(childPosToRemain, res);
555564
NUnit.Framework.Assert.IsFalse(specialScriptLayoutResults.IsEmpty());
556565
Tab tab = new Tab();
557566
tab.SetProperty(Property.FLOAT, FloatPropertyValue.RIGHT);
558567
TabRenderer tabRenderer = new TabRenderer(tab);
559-
int childPosNotToBeAdded = 0;
560-
LineRenderer.UpdateSpecialScriptLayoutResults(specialScriptLayoutResults, tabRenderer, childPosNotToBeAdded
561-
, res);
568+
LineRenderer.MinMaxWidthOfTextRendererSequenceHelper minMaxWidthOfTextRendererSequenceHelper = new LineRenderer.MinMaxWidthOfTextRendererSequenceHelper
569+
(0f, 0f, false);
570+
AbstractWidthHandler widthHandler = new MaxSumWidthHandler(new MinMaxWidth());
571+
PdfDocument pdfDocument = new PdfDocument(new PdfWriter(new MemoryStream()));
572+
Document document = new Document(pdfDocument);
573+
LineRenderer lineRenderer = new LineRenderer();
574+
lineRenderer.SetParent(document.GetRenderer());
575+
lineRenderer.AddChild(tabRenderer);
576+
int childPosNotToBeAdded = 1;
577+
lineRenderer.UpdateSpecialScriptLayoutResults(specialScriptLayoutResults, tabRenderer, childPosNotToBeAdded
578+
, res, minMaxWidthOfTextRendererSequenceHelper, false, widthHandler);
562579
NUnit.Framework.Assert.IsTrue(specialScriptLayoutResults.ContainsKey(childPosToRemain));
563580
NUnit.Framework.Assert.IsFalse(specialScriptLayoutResults.ContainsKey(childPosNotToBeAdded));
564581
}
@@ -568,10 +585,19 @@ public virtual void UpdateSpecialScriptLayoutResultsTextRendererWithNoSpecialScr
568585
IDictionary<int, LayoutResult> specialScriptLayoutResults = new Dictionary<int, LayoutResult>();
569586
LayoutResult res = new LayoutResult(LayoutResult.NOTHING, new LayoutArea(0, new Rectangle(0, 0, 10, 10)),
570587
null, null);
571-
specialScriptLayoutResults.Put(-1, res);
588+
specialScriptLayoutResults.Put(0, res);
572589
NUnit.Framework.Assert.IsFalse(specialScriptLayoutResults.IsEmpty());
573590
TextRenderer textRenderer = new TextRenderer(new iText.Layout.Element.Text("whatever"));
574-
LineRenderer.UpdateSpecialScriptLayoutResults(specialScriptLayoutResults, textRenderer, 1, res);
591+
PdfDocument pdfDocument = new PdfDocument(new PdfWriter(new MemoryStream()));
592+
Document document = new Document(pdfDocument);
593+
LineRenderer lineRenderer = new LineRenderer();
594+
lineRenderer.SetParent(document.GetRenderer());
595+
lineRenderer.AddChild(textRenderer);
596+
LineRenderer.MinMaxWidthOfTextRendererSequenceHelper minMaxWidthOfTextRendererSequenceHelper = new LineRenderer.MinMaxWidthOfTextRendererSequenceHelper
597+
(0f, 0f, false);
598+
AbstractWidthHandler widthHandler = new MaxSumWidthHandler(new MinMaxWidth());
599+
lineRenderer.UpdateSpecialScriptLayoutResults(specialScriptLayoutResults, textRenderer, 1, res, minMaxWidthOfTextRendererSequenceHelper
600+
, true, widthHandler);
575601
NUnit.Framework.Assert.IsTrue(specialScriptLayoutResults.IsEmpty());
576602
}
577603

@@ -585,8 +611,17 @@ public virtual void UpdateSpecialScriptLayoutResultsTextRendererWithSpecialScrip
585611
NUnit.Framework.Assert.IsFalse(specialScriptLayoutResults.IsEmpty());
586612
TextRenderer textRenderer = new TextRenderer(new iText.Layout.Element.Text("whatever"));
587613
textRenderer.SetSpecialScriptsWordBreakPoints(new List<int>(JavaUtil.ArraysAsList(-1)));
614+
PdfDocument pdfDocument = new PdfDocument(new PdfWriter(new MemoryStream()));
615+
Document document = new Document(pdfDocument);
616+
LineRenderer lineRenderer = new LineRenderer();
617+
lineRenderer.SetParent(document.GetRenderer());
618+
lineRenderer.AddChild(textRenderer);
619+
LineRenderer.MinMaxWidthOfTextRendererSequenceHelper minMaxWidthOfTextRendererSequenceHelper = new LineRenderer.MinMaxWidthOfTextRendererSequenceHelper
620+
(0f, 0f, false);
621+
AbstractWidthHandler widthHandler = new MaxSumWidthHandler(new MinMaxWidth());
588622
int secondKey = firstKey + 1;
589-
LineRenderer.UpdateSpecialScriptLayoutResults(specialScriptLayoutResults, textRenderer, secondKey, res);
623+
lineRenderer.UpdateSpecialScriptLayoutResults(specialScriptLayoutResults, textRenderer, secondKey, res, minMaxWidthOfTextRendererSequenceHelper
624+
, true, widthHandler);
590625
NUnit.Framework.Assert.IsTrue(specialScriptLayoutResults.ContainsKey(firstKey));
591626
NUnit.Framework.Assert.IsTrue(specialScriptLayoutResults.ContainsKey(secondKey));
592627
}

itext/itext.layout/itext/layout/layout/TextLayoutResult.cs

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,10 @@ public class TextLayoutResult : MinMaxWidthLayoutResult {
6464

6565
protected internal bool lineEndsWithSplitCharacterOrWhiteSpace = false;
6666

67+
protected internal float leftMinWidth;
68+
69+
protected internal float rightMinWidth;
70+
6771
/// <summary>
6872
/// Creates the
6973
/// <see cref="LayoutResult"/>
@@ -250,5 +254,65 @@ public virtual iText.Layout.Layout.TextLayoutResult SetLineEndsWithSplitCharacte
250254
public virtual bool IsLineEndsWithSplitCharacterOrWhiteSpace() {
251255
return lineEndsWithSplitCharacterOrWhiteSpace;
252256
}
257+
258+
/// <summary>Sets min width of the leftmost unbreakable part of the TextRenderer#line after layout.</summary>
259+
/// <remarks>
260+
/// Sets min width of the leftmost unbreakable part of the TextRenderer#line after layout.
261+
/// This value includes left-side additional width, i.e. left margin, border and padding widths.
262+
/// In case when entire TextRenderer#line is unbreakable, leftMinWidth also includes right-side additional width.
263+
/// </remarks>
264+
/// <param name="leftMinWidth">min width of the leftmost unbreakable part of the TextRenderer#line after layout.
265+
/// </param>
266+
/// <returns>
267+
///
268+
/// <see cref="TextLayoutResult">this layout result</see>
269+
/// the setting was applied on.
270+
/// </returns>
271+
public virtual iText.Layout.Layout.TextLayoutResult SetLeftMinWidth(float leftMinWidth) {
272+
this.leftMinWidth = leftMinWidth;
273+
return this;
274+
}
275+
276+
/// <summary>Gets min width of the leftmost unbreakable part of the TextRenderer#line after layout.</summary>
277+
/// <remarks>
278+
/// Gets min width of the leftmost unbreakable part of the TextRenderer#line after layout.
279+
/// This value leftMinWidth includes left-side additional width, i.e. left margin, border and padding widths.
280+
/// In case when entire TextRenderer#line is unbreakable, leftMinWidth also includes right-side additional width.
281+
/// </remarks>
282+
/// <returns>min width of the leftmost unbreakable part of the TextRenderer#line after layout.</returns>
283+
public virtual float GetLeftMinWidth() {
284+
return leftMinWidth;
285+
}
286+
287+
/// <summary>Sets min width of the rightmost unbreakable part of the TextRenderer#line after layout.</summary>
288+
/// <remarks>
289+
/// Sets min width of the rightmost unbreakable part of the TextRenderer#line after layout.
290+
/// This value includes right-side additional width, i.e. right margin, border and padding widths.
291+
/// In case when entire TextRenderer#line is unbreakable, this value must be -1
292+
/// and right-side additional width must be included in leftMinWidth.
293+
/// </remarks>
294+
/// <param name="rightMinWidth">min width of the rightmost unbreakable part of the TextRenderer#line after layout.
295+
/// </param>
296+
/// <returns>
297+
///
298+
/// <see cref="TextLayoutResult">this layout result</see>
299+
/// the setting was applied on.
300+
/// </returns>
301+
public virtual iText.Layout.Layout.TextLayoutResult SetRightMinWidth(float rightMinWidth) {
302+
this.rightMinWidth = rightMinWidth;
303+
return this;
304+
}
305+
306+
/// <summary>Gets min width of the rightmost unbreakable part of the TextRenderer#line after layout.</summary>
307+
/// <remarks>
308+
/// Gets min width of the rightmost unbreakable part of the TextRenderer#line after layout.
309+
/// This value includes right-side additional width, i.e. right margin, border and padding widths.
310+
/// In case when entire TextRenderer#line is unbreakable, this value must be -1
311+
/// and right-side additional width must be included in leftMinWidth.
312+
/// </remarks>
313+
/// <returns>min width of the leftmost unbreakable part of the TextRenderer#line after layout.</returns>
314+
public virtual float GetRightMinWidth() {
315+
return rightMinWidth;
316+
}
253317
}
254318
}

0 commit comments

Comments
 (0)