itext 7 pdf如何防止页面右侧的文本溢出

itext 7 pdf how to prevent text overflow on right side of the page

我正在使用 itextpdf 7 (7.2.0) 创建 pdf 文件。然而,尽管 TOC 部分呈现得非常好,但在内容部分中,文本会溢出。这是我生成 pdf 的代码:

public class Main {
    public static void main(String[] args) throws IOException {
        PdfWriter writer = new PdfWriter("fiftyfourthPdf.pdf");
        PdfDocument pdf = new PdfDocument(writer);
        Document document = new Document(pdf, PageSize.A4,false);
        //document.setMargins(30,10,36,10);

// Create a PdfFont
        PdfFont font = PdfFontFactory.createFont(StandardFonts.TIMES_ROMAN,"Cp1254");

        document
                .setTextAlignment(TextAlignment.JUSTIFIED)
                .setFont(font)
                .setFontSize(11);
        PdfOutline outline = null;
        java.util.List<AbstractMap.SimpleEntry<String, AbstractMap.SimpleEntry<String, Integer>>> toc = new ArrayList<>();
        for(int i=0;i<5000;i++){
            String line = "This is paragraph " + String.valueOf(i+1)+ " ";
            line = line.concat(line).concat(line).concat(line).concat(line).concat(line);
            Paragraph p = new Paragraph(line);
            p.setKeepTogether(true);
            document.add(p.setFont(font).setFontSize(10).setHorizontalAlignment(HorizontalAlignment.CENTER).setTextAlignment(TextAlignment.LEFT));

            //PROCESS FOR TOC
            String name = "para " + String.valueOf(i+1);
            outline = createOutline(outline,pdf,line ,name );
            AbstractMap.SimpleEntry<String, Integer> titlePage = new AbstractMap.SimpleEntry(line, pdf.getNumberOfPages());
            p
                    .setFont(font)
                    .setFontSize(12)
                    //.setKeepWithNext(true)
                    .setDestination(name)

                    // Add the current page number to the table of contents list
                    .setNextRenderer(new UpdatePageRenderer(p));
            toc.add(new AbstractMap.SimpleEntry(name, titlePage));

        }

        int contentPageNumber = pdf.getNumberOfPages();

        for (int i = 1; i <= contentPageNumber; i++) {

            // Write aligned text to the specified by parameters point
            document.showTextAligned(new Paragraph(String.format("Sayfa %s / %s", i, contentPageNumber)).setFontSize(10),
                    559, 26, i, TextAlignment.RIGHT, VerticalAlignment.MIDDLE, 0);
        }

        //BEGINNING OF TOC
        document.add(new AreaBreak());
        Paragraph p = new Paragraph("Table of Contents")
                .setFont(font)
                .setDestination("toc");
        document.add(p);
        java.util.List<TabStop> tabStops = new ArrayList<>();
        tabStops.add(new TabStop(580, TabAlignment.RIGHT, new DottedLine()));
        for (AbstractMap.SimpleEntry<String, AbstractMap.SimpleEntry<String, Integer>> entry : toc) {
            AbstractMap.SimpleEntry<String, Integer> text = entry.getValue();
            p = new Paragraph()
                    .addTabStops(tabStops)
                    .add(text.getKey())
                    .add(new Tab())
                    .add(String.valueOf(text.getValue()))
                    .setAction(PdfAction.createGoTo(entry.getKey()));
            document.add(p);
        }



        // Move the table of contents to the first page
        int tocPageNumber = pdf.getNumberOfPages();
        for (int i = 1; i <= tocPageNumber; i++) {

            // Write aligned text to the specified by parameters point
            document.showTextAligned(new Paragraph("\n footer text\n second line\nthird line").setFontColor(ColorConstants.RED).setFontSize(8),
                    300, 26, i, TextAlignment.CENTER, VerticalAlignment.MIDDLE, 0);
        }

        document.flush();
        for(int z = 0; z< (tocPageNumber - contentPageNumber ); z++){
            pdf.movePage(tocPageNumber,1);
            pdf.getPage(1).setPageLabel(PageLabelNumberingStyle.UPPERCASE_LETTERS,
                    null, 1);
        }


        //pdf.movePage(tocPageNumber, 1);

        // Add page labels
        /*pdf.getPage(1).setPageLabel(PageLabelNumberingStyle.UPPERCASE_LETTERS,
                null, 1);*/
        pdf.getPage(tocPageNumber - contentPageNumber + 1).setPageLabel(PageLabelNumberingStyle.DECIMAL_ARABIC_NUMERALS,
                null, 1);


        document.close();

    }
    private static PdfOutline createOutline(PdfOutline outline, PdfDocument pdf, String title, String name) {
        if (outline == null) {
            outline = pdf.getOutlines(false);
            outline = outline.addOutline(title);
            outline.addDestination(PdfDestination.makeDestination(new PdfString(name)));
        } else {
            PdfOutline kid = outline.addOutline(title);
            kid.addDestination(PdfDestination.makeDestination(new PdfString(name)));
        }

        return outline;
    }
    private static class UpdatePageRenderer extends ParagraphRenderer {
        protected AbstractMap.SimpleEntry<String, Integer> entry;

        public UpdatePageRenderer(Paragraph modelElement, AbstractMap.SimpleEntry<String, Integer> entry) {
            super(modelElement);
            this.entry = entry;
        }
        public UpdatePageRenderer(Paragraph modelElement) {
            super(modelElement);
        }

        @Override
        public LayoutResult layout(LayoutContext layoutContext) {
            LayoutResult result = super.layout(layoutContext);
            //entry.setValue(layoutContext.getArea().getPageNumber());
            if (result.getStatus() != LayoutResult.FULL) {
                if (null != result.getOverflowRenderer()) {
                    result.getOverflowRenderer().setProperty(
                            Property.LEADING,
                            result.getOverflowRenderer().getModelElement().getDefaultProperty(Property.LEADING));
                } else {
                    // if overflow renderer is null, that could mean that the whole renderer will overflow
                    setProperty(
                            Property.LEADING,
                            result.getOverflowRenderer().getModelElement().getDefaultProperty(Property.LEADING));
                }
            }
            return result;
        }

        @Override
        // If not overriden, the default renderer will be used for the overflown part of the corresponding paragraph
        public IRenderer getNextRenderer() {
            return new UpdatePageRenderer((Paragraph) this.getModelElement());
        }

      
    }

}

目录部分和内容部分的截图如下:

TOC :

Content :

我错过了什么?谢谢大家的帮助。

更新

当我添加下面的行时,它呈现时没有溢出,但 TOC 和内容部分的页边距不同(TOC 边距远大于内容边距)。请看附图:

document.setMargins(30,60,36,20);

目录和内容之间的右边距差异:

更新 2:

当我评论这行时

document.setMargins(30,60,36,20);

并在行中设置字体大小:

document.add(p.setFont(font).setFontSize(10).setHorizontalAlignment(HorizontalAlignment.CENTER).setTextAlignment(TextAlignment.LEFT));

到 12 然后它呈现正常。字体大小可能对页面内容和页边距造成什么差异?没有标准的页边距和页面设置吗?我是不是在不知不觉中(我是 itextpdf 的新手)弄乱了一些标准实现?

TL; DR:要么在

中删除setFontSize
p
                    .setFont(font)
                    .setFontSize(12)
                    //.setKeepWithNext(true)
                    .setDestination(name)

更改 setFontSize(10) -> setFontSize(12) in

document.add(p.setFont(font).setFontSize(10).setHorizontalAlignment(HorizontalAlignment.CENTER).setTextAlignment(TextAlignment.LEFT));

说明:您将 Document 设置为不立即刷新添加到该文档的元素,使用以下行:

Document document = new Document(pdf, PageSize.A4,false);

然后使用以下行将字体大小等于 10 的段落元素添加到文档中:

document.add(p.setFont(font).setFontSize(10).setHorizontalAlignment(HorizontalAlignment.CENTER).setTextAlignment(TextAlignment.LEFT));

元素正在布局(拆分成行等),但现在绘制在页面上。然后你做.setFontSize(12),这个新的字体大小只适用于draw,所以iText计算出X个字符可以放在一行中,假设字体大小是10,而实际上字体大小是12,显然一行中可以容纳的字符更少。

将字体大小两次设置为不同的值没有任何意义 - 只需选择一个您希望在生成的文档中看到的值并设置一次即可。