如何撤消段落添加?

How can I undo paragraph addings?

我正在使用 iText 7.2.1。

我有多篇不同长度的长篇文章。我需要做的是:

  1. 在候选集中选一篇文章加入我的文档。新添加的文章将紧接上一篇文章。可能会有自动换页。

  2. 检查这篇新添加的文章是否符合某些标准。 (例如:检查它的结束行是否在页面的正确位置)

  3. 如果不是,请撤消此添加,然后尝试候选集中的下一篇文章。

Document 似乎没有“撤销”。所以我想知道我是否可以复制我当前的文档进行测试。或者在添加之前有没有其他的测试方法?

在问题的评论部分中提出了 relayout 的想法,但是,尚未证明如何有效地将其应用于您的案例。我是这样看待你的要求的:

  1. 您想逐段考虑。在其余的答案中,我将这些意译称为“候选人”。
  2. 对于每个你想要布局的候选人,检查它是否符合你的一些标准。
  3. 如果答案是肯定的,那么您想将此段添加到文档中。
  4. 无论如何,无论是否添加了候选人,您都希望继续进行其他候选人。

我想明确提及“布局”一词而不是“添加”:在下面提出的解决方案中,我将尝试布局候选而不实际将它们添加到文档中。一旦候选人被布局,您可以根据您的标准检查它,如果它符合他们,那么应该添加候选人。

下面是代码的主要部分。如您所见,我在这里执行以下操作:在添加请求的段落数之前,我生成随机大小的段落并在 isParagraphAccepted 的帮助下检查它们是否被接受。如果为真,那么我将它们添加到文档中并减少要添加的段落数。

    PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outFileName));
    Document doc = new Document(pdfDoc);

    RootRenderer rootRenderer = doc.getRenderer();
    Rectangle defaultArea = pdfDoc.getDefaultPageSize();
    
    int paragraphsToAddCount = 10;

    LoremIpsum lorem = LoremIpsum.getInstance();
    int minLoremCount = 25;
    int maxLoremCount = 50;

    int counter = 0;
    while (paragraphsToAddCount > 0) {
        Paragraph p = new Paragraph(lorem.getParagraphs(minLoremCount, maxLoremCount));
        if (isParagraphAccepted(p, rootRenderer, defaultArea)) {
            doc.add(p);
            paragraphsToAddCount--;
        }
        counter++;
    }

    System.out.println("We have considered " + counter + " paragraphs.");
    doc.close();

然而,魔术是在isParagraphAccepted完成的,所以让我们来看看:

    boolean isParagraphAccepted(Paragraph p, RootRenderer rootRenderer, Rectangle defaultArea) {
    Rectangle currentArea = null == rootRenderer.getCurrentArea()
            ? defaultArea
            : rootRenderer.getCurrentArea().getBBox();

    IRenderer paragraphRenderer = p.createRendererSubTree().setParent(rootRenderer);
    LayoutResult layoutResult = paragraphRenderer.layout(new LayoutContext(new LayoutArea(0, currentArea)));
    while (LayoutResult.FULL != layoutResult.getStatus()) {
        currentArea = defaultArea;
        paragraphRenderer = layoutResult.getOverflowRenderer();
        layoutResult = paragraphRenderer.layout(new LayoutContext(new LayoutArea(0, currentArea)));
    }

    // checking against some criteria
    return layoutResult.getOccupiedArea().getBBox().getHeight() > 500;
}

基本上,在这种方法中完成了以下工作:pararaph 逐页进行布局,直到它最终完全布局,然后我根据一些标准检查它在最后一页上占据的区域。