Skip to content

Commit 8147565

Browse files
SnipxiText-CI
authored andcommitted
Fix counter(pages) calculation in case page is trimmed at the end
DEVSIX-2999
1 parent 45c2a1e commit 8147565

File tree

4 files changed

+110
-24
lines changed

4 files changed

+110
-24
lines changed

src/main/java/com/itextpdf/html2pdf/attach/impl/layout/HtmlDocumentRenderer.java

Lines changed: 58 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -197,16 +197,7 @@ public void close() {
197197
super.addChild(r);
198198
}
199199
super.close();
200-
if (TRIM_LAST_BLANK_PAGE) {
201-
PdfDocument pdfDocument = document.getPdfDocument();
202-
if (pdfDocument.getNumberOfPages() > 1) {
203-
PdfPage lastPage = pdfDocument.getLastPage();
204-
if (lastPage.getContentStreamCount() == 1 && lastPage.getContentStream(0).getOutputStream().getCurrentPos() <= 0) {
205-
// Remove last empty page
206-
pdfDocument.removePage(pdfDocument.getNumberOfPages());
207-
}
208-
}
209-
}
200+
trimLastPageIfNecessary();
210201
document.getPdfDocument().removeEventHandler(PdfDocumentEvent.END_PAGE, handler);
211202
for (int i = 1; i <= document.getPdfDocument().getNumberOfPages(); ++i) {
212203
PdfPage page = document.getPdfDocument().getPage(i);
@@ -232,11 +223,55 @@ public IRenderer getNextRenderer() {
232223
relayoutRenderer.firstPageProc = firstPageProc.reset(defaultPageSize, defaultPageMargins);
233224
relayoutRenderer.leftPageProc = leftPageProc.reset(defaultPageSize, defaultPageMargins);
234225
relayoutRenderer.rightPageProc = rightPageProc.reset(defaultPageSize, defaultPageMargins);
235-
relayoutRenderer.estimatedNumberOfPages = currentPageNumber;
226+
relayoutRenderer.estimatedNumberOfPages = currentPageNumber - simulateTrimLastPage();
236227
relayoutRenderer.handler = handler.setHtmlDocumentRenderer(relayoutRenderer);
237228
return relayoutRenderer;
238229
}
239230

231+
boolean shouldAttemptTrimLastPage() {
232+
return TRIM_LAST_BLANK_PAGE && document.getPdfDocument().getNumberOfPages() > 1;
233+
}
234+
235+
void trimLastPageIfNecessary() {
236+
if (shouldAttemptTrimLastPage()) {
237+
PdfDocument pdfDocument = document.getPdfDocument();
238+
PdfPage lastPage = pdfDocument.getLastPage();
239+
if (lastPage.getContentStreamCount() == 1 && lastPage.getContentStream(0).getOutputStream().getCurrentPos() <= 0) {
240+
// Remove last empty page
241+
pdfDocument.removePage(pdfDocument.getNumberOfPages());
242+
}
243+
}
244+
}
245+
246+
/**
247+
* Returns the number of pages that will be trimmed on {@link #close()}
248+
* @return 0 if no pages will be trimmed, or positive number of trimmed pages in case any are trimmed
249+
*/
250+
int simulateTrimLastPage() {
251+
if (shouldAttemptTrimLastPage()) {
252+
int lastPageNumber = document.getPdfDocument().getNumberOfPages();
253+
// At the moment we only check if some element was positioned on this page
254+
// However, there might theoretically be an inconsistency with the method that
255+
// actually does the trimming because that method checks the canvas output only.
256+
// We might want to simulate drawing on canvas here in the future, or possibly
257+
// consider invisible elements in the method that actually does the trimming
258+
boolean willAnyContentBeDrawnOnLastPage = false;
259+
for (IRenderer renderer : childRenderers) {
260+
if (renderer.getOccupiedArea().getPageNumber() == lastPageNumber) {
261+
willAnyContentBeDrawnOnLastPage = true;
262+
}
263+
}
264+
for (IRenderer renderer : positionedRenderers) {
265+
if (renderer.getOccupiedArea().getPageNumber() == lastPageNumber) {
266+
willAnyContentBeDrawnOnLastPage = true;
267+
}
268+
}
269+
return willAnyContentBeDrawnOnLastPage ? 0 : 1;
270+
} else {
271+
return 0;
272+
}
273+
}
274+
240275
/* (non-Javadoc)
241276
* @see com.itextpdf.layout.renderer.DocumentRenderer#updateCurrentArea(com.itextpdf.layout.layout.LayoutResult)
242277
*/
@@ -385,6 +420,18 @@ int getEstimatedNumberOfPages() {
385420
return estimatedNumberOfPages;
386421
}
387422

423+
private static boolean isRunningElementsOnly(IRenderer waitingElement) {
424+
boolean res;
425+
if (res = waitingElement instanceof ParagraphRenderer && !waitingElement.getChildRenderers().isEmpty()) {
426+
List<IRenderer> childRenderers = waitingElement.getChildRenderers();
427+
int i = 0;
428+
while (res && i < childRenderers.size()) {
429+
res = childRenderers.get(i++) instanceof RunningElement.RunningElementRenderer;
430+
}
431+
}
432+
return res;
433+
}
434+
388435
/**
389436
* Gets a page processor for the page.
390437
*
@@ -422,18 +469,6 @@ private boolean isPageRight(int pageNum) {
422469
return !isPageLeft(pageNum);
423470
}
424471

425-
private static boolean isRunningElementsOnly(IRenderer waitingElement) {
426-
boolean res;
427-
if (res = waitingElement instanceof ParagraphRenderer && !waitingElement.getChildRenderers().isEmpty()) {
428-
List<IRenderer> childRenderers = waitingElement.getChildRenderers();
429-
int i = 0;
430-
while (res && i < childRenderers.size()) {
431-
res = childRenderers.get(i++) instanceof RunningElement.RunningElementRenderer;
432-
}
433-
}
434-
return res;
435-
}
436-
437472
private static class PageMarginBoxesDrawingHandler implements IEventHandler {
438473
private HtmlDocumentRenderer htmlDocumentRenderer;
439474

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package com.itextpdf.html2pdf.attach.impl.layout;
2+
3+
import com.itextpdf.io.source.ByteArrayOutputStream;
4+
import com.itextpdf.kernel.pdf.PdfDocument;
5+
import com.itextpdf.kernel.pdf.PdfWriter;
6+
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
7+
import com.itextpdf.layout.Document;
8+
import com.itextpdf.test.annotations.type.UnitTest;
9+
import org.junit.Assert;
10+
import org.junit.Test;
11+
import org.junit.experimental.categories.Category;
12+
13+
@Category(UnitTest.class)
14+
public class HtmlDocumentRendererTest {
15+
16+
@Test
17+
public void shouldAttemptTrimLastPageTest() {
18+
PdfDocument pdfDocument = new PdfDocument(new PdfWriter(new ByteArrayOutputStream()));
19+
Document document = new Document(pdfDocument);
20+
HtmlDocumentRenderer documentRenderer = new HtmlDocumentRenderer(document, false);
21+
document.setRenderer(documentRenderer);
22+
pdfDocument.addNewPage();
23+
24+
Assert.assertEquals(1, pdfDocument.getNumberOfPages());
25+
// For one-page documents it does not make sense to attempt to trim last page
26+
Assert.assertFalse(documentRenderer.shouldAttemptTrimLastPage());
27+
28+
pdfDocument.addNewPage();
29+
Assert.assertEquals(2, pdfDocument.getNumberOfPages());
30+
// If there are more than one page, we try to trim last page
31+
Assert.assertTrue(documentRenderer.shouldAttemptTrimLastPage());
32+
}
33+
34+
@Test
35+
public void trimLastPageIfNecessaryTest() {
36+
PdfDocument pdfDocument = new PdfDocument(new PdfWriter(new ByteArrayOutputStream()));
37+
Document document = new Document(pdfDocument);
38+
HtmlDocumentRenderer documentRenderer = new HtmlDocumentRenderer(document, false);
39+
document.setRenderer(documentRenderer);
40+
pdfDocument.addNewPage();
41+
pdfDocument.addNewPage();
42+
new PdfCanvas(pdfDocument.getLastPage()).moveTo(10, 10).lineTo(20, 20).stroke();
43+
pdfDocument.addNewPage();
44+
45+
Assert.assertEquals(3, pdfDocument.getNumberOfPages());
46+
documentRenderer.trimLastPageIfNecessary();
47+
Assert.assertEquals(2, pdfDocument.getNumberOfPages());
48+
documentRenderer.trimLastPageIfNecessary();
49+
Assert.assertEquals(2, pdfDocument.getNumberOfPages());
50+
}
51+
52+
}

src/test/java/com/itextpdf/html2pdf/css/CounterTest.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,6 @@ public void pageCounter03Test() throws IOException, InterruptedException {
8282
}
8383

8484
@Test
85-
// TODO cmp file to be fixed after DEVSIX-2999 is done
8685
public void pageCounter04Test() throws IOException, InterruptedException {
8786
convertToPdfAndCompare("page_counter04", sourceFolder, destinationFolder);
8887
}
Binary file not shown.

0 commit comments

Comments
 (0)