In my iText 7 PDF generation, in a Text
block (which is within a Paragraph
), I need to preserve whitespace that explicitly starts on a new line.
Here's the Custom Renderer I have right now:
// This custom text renderer keeps leading whitespace (by doing nothing in trimFirst()) which would otherwise be automatically trimmed
public class PdfKeepLeadingWhitespaceTextRenderer extends TextRenderer {
public PdfKeepLeadingWhitespaceTextRenderer(Text textElement) {
super(textElement);
}
@Override
public IRenderer getNextRenderer() {
return new PdfKeepLeadingWhitespaceTextRenderer((Text) getModelElement());
}
@Override
public void trimFirst() {
// Do nothing. This will keep leading whitespace
}
}
Java code:
Paragraph paragraphResponse = new Paragraph();
Text textResponse = new Text(pdfData.getRespText());
textResponse.setNextRenderer(new PdfKeepLeadingWhitespaceTextRenderer(textResponse));
paragraphResponse.add(textResponse);
It works, so if I have something like
Text 1
Text 2 on new line
it will keep the whitespace on Line 2, which is correct.
But if text flows without an explicit newline in a paragraph, then the whitespace created "accidentally" (i.e. not as an intentional space on a new line) is also preserved and indented, which is wrong (note line 3):
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt
ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation
ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in
reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur
sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id
est laborum.
How do I keep the leading whitespace when it's intentional on a new line only?
In my iText 7 PDF generation, in a Text
block (which is within a Paragraph
), I need to preserve whitespace that explicitly starts on a new line.
Here's the Custom Renderer I have right now:
// This custom text renderer keeps leading whitespace (by doing nothing in trimFirst()) which would otherwise be automatically trimmed
public class PdfKeepLeadingWhitespaceTextRenderer extends TextRenderer {
public PdfKeepLeadingWhitespaceTextRenderer(Text textElement) {
super(textElement);
}
@Override
public IRenderer getNextRenderer() {
return new PdfKeepLeadingWhitespaceTextRenderer((Text) getModelElement());
}
@Override
public void trimFirst() {
// Do nothing. This will keep leading whitespace
}
}
Java code:
Paragraph paragraphResponse = new Paragraph();
Text textResponse = new Text(pdfData.getRespText());
textResponse.setNextRenderer(new PdfKeepLeadingWhitespaceTextRenderer(textResponse));
paragraphResponse.add(textResponse);
It works, so if I have something like
Text 1
Text 2 on new line
it will keep the whitespace on Line 2, which is correct.
But if text flows without an explicit newline in a paragraph, then the whitespace created "accidentally" (i.e. not as an intentional space on a new line) is also preserved and indented, which is wrong (note line 3):
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt
ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation
ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in
reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur
sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id
est laborum.
How do I keep the leading whitespace when it's intentional on a new line only?
Share Improve this question edited Mar 13 at 15:10 gene b. asked Mar 13 at 15:05 gene b.gene b. 12.1k30 gold badges139 silver badges270 bronze badges1 Answer
Reset to default 2You will need to modify your custom TextRenderer
. iText has special TextRenderer
, which has more or less similar logic, it's called FormFieldValueNonTrimmingTextRenderer
. Unfortunately it is package private, so you won't be able to just use it. Also the logic of removing accidental whitespaces is slightly different.
However you can make it yourself. This is how your custom renderer will look like:
public class PdfKeepLeadingWhitespaceTextRenderer extends TextRenderer {
private boolean callTrimFirst = false;
public PdfKeepLeadingWhitespaceTextRenderer(Text textElement) {
super(textElement);
}
@Override
public IRenderer getNextRenderer() {
return new PdfKeepLeadingWhitespaceTextRenderer((Text) getModelElement());
}
@Override
public LayoutResult layout(LayoutContext layoutContext) {
LayoutResult baseLayoutResult = super.layout(layoutContext);
if (baseLayoutResult instanceof TextLayoutResult &&
baseLayoutResult.getOverflowRenderer()
instanceof PdfKeepLeadingWhitespaceTextRenderer &&
!((TextLayoutResult) baseLayoutResult).isSplitForcedByNewline) {
((PdfKeepLeadingWhitespaceTextRenderer) baseLayoutResult.getOverflowRenderer())
.setCallTrimFirst(true);
}
return baseLayoutResult;
}
@Override
public void trimFirst() {
if (callTrimFirst) {
super.trimFirst();
}
}
private void setCallTrimFirst(boolean callTrimFirst) {
this.callTrimFirst = callTrimFirst;
}
}
Custom class in iText also contains an override for createCopy(GlyphLine gl, PdfFont font)
method, it might also be required for your custom implementation in case of complicated fonts.