admin管理员组

文章数量:1389820

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 badges
Add a comment  | 

1 Answer 1

Reset to default 2

You 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.

本文标签: itextKeep leading whitespacebut only on an explicit new lineStack Overflow