How can I enforce an even PDF page count with FlyingSaucer?

134 views Asked by At

I am working on a Grails project that uses the Flying Saucer library (via the Rendering plugin) to generate PDFs. I need those PDFs, which can have arbitrary lengths, to be forced to have an even page count. In other words: if the page count comes out odd, I need an empty page to be added to the end.

How can I achieve this? According to the user guide it should honour the normal CSS pagination rules, but that doesn't seem to work. I have tried rules like:

body {
    page-break-after: right;
}

But they just seem to be ignored. I have tried variations such as html instead of body, left instead of right and even always.

Is this something this library can do? Perhaps there is some way to more directly tell it to create an even number of pages, not through CSS?

1

There are 1 answers

1
raner On

I ran into the same issue and was unable to solve it just with CSS (I think that @CBroe's comment is spot on).

The solution that ended up working for me was pretty hacky: I always add an extra blank page at the end of the document (by adding <div style="page-break-before: always;">&#0160;</div> as the last element in the body), and then cut off that extra page again if the rendered document ends up having an odd number of pages.

I do the "cutting" by attaching a PDFCreationListener that trims the renderer's internal page array to an even size (code is in Kotlin, but can be easily adjusted for other languages):

    renderer.listener = object: DefaultPDFCreationListener() {
        override fun preOpen(iTextRenderer: ITextRenderer?) {
            val pages: List<Any?> = renderer.rootBox.layer.pages
            pageCount[0] = pages.size.and(1.inv())
            renderer.rootBox.layer.pages = pages.subList(0, pageCount[0]?:0)
        }
    }

I the above code, renderer is the ITextRenderer, which means that this code is specifically for the flying-saucer-pdf-itext5 renderer. I'm not sure how this would need to be adjusted for the PDFBox-based renderer.