最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

itext - Keep leading whitespace, but only on an explicit new line - Stack Overflow

programmeradmin2浏览0评论

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.

发布评论

评论列表(0)

  1. 暂无评论