0

I am using openhtmltopdf (1.0.10) to get a PDF printout to be printed by thermal printers (with roll paper).

I have not set any CSS width or height values to any of the HTML elements, instead I am setting the PdfRendererBuilder#useDefaultPageSize method with my desired width and height values in MM.

The width is fixed and set to 80mm, but I need to calculate the rendered height of the document to give it to the above-mentioned method, to avoid splitting my printout into several pages, resulting in the printer cutting the paper at the end of every page. In other words I need a long continious one page PDF.

To achieve this I used the suggestions mentioned here, and it works, but not in all cases and as precisely as I expect.

The problem is that only when the content fits in one page (PageBox) (a default page height is internally set, regardless of HTML page having no heights set, resulting in generation of multiple pages when the content is large), the calculated height works correctly, but when it is greater that one page, I get an extra blank space (space between the bottom of my .container HTML element and the bottom of the body element) added to the bottom of the rendered PDF, which grows in height every couple of pages being added (3 to be more precise).

I will share with you a simplified snippet of my HTML and the code, and also a simple visual representation of what I get as the result.

HTML to be rendered (I have added the red body bg to be visible in visual outcome):

<!DOCTYPE html>
<html>

<head>
    <title>Printout</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />

    <style>
        @page {
            margin: 0;
        }

        body {
            background-color: #ff0000;
        }

        .container * {
            page-break-inside: avoid;
        }

        .container {
            padding: 5mm;
            overflow: hidden;
            page-break-inside: avoid;
            background-color: white;
        }
    </style>
</head>

<body>
    <section class="container">

        <header>
            HEADER CONTENT
        </header>

        <section>
            MAIN CONTENT
        </section>

        <footer>
            FOOTER CONTENT
        </footer>

    </section>
</body>

</html>

Calculation of the rendered height and assigning it to the builder:

private static void createPdfForPrinting(OutputStream outputStream, Document document)
throws IOException {

PdfRendererBuilder pdfBuilder = new PdfRendererBuilder();

try (PdfBoxRenderer pdfRenderer = pdfBuilder
    .withW3cDocument(document, "/")
    .useFastMode()
    .toStream(outputStream)
    .buildPdfRenderer()) {

    pdfRenderer.layout();
    Layer mainLayer = pdfRenderer.getRootBox().getContainingLayer();
    float renderedHeight = findMaxLayerY(mainLayer);
    float pageHeight = convertToMillimeters(renderedHeight);

    pdfBuilder.useDefaultPageSize(80, pageHeight, BaseRendererBuilder.PageSizeUnits.MM)
        .run();
  }
}

private static int findMaxLayerY(Layer layer) {
    int maxLayerY = layer.getMaster().getAbsY() + layer.getMaster().getHeight();

    int maxChildY = layer.getChildren()
        .stream()
        .mapToInt(RendererUtil::findMaxLayerY)
        .max()
        .orElse(0);

    return Math.max(maxChildY, maxLayerY);
} 

private static float convertToMillimeters(float pixels) {
    final float PDF_DOTS_PER_PIXEL = 20.0f;
    final float MM_PER_INCH = 25.4f;
    final int PIXELS_PER_INCH = 96;
    return (pixels / PDF_DOTS_PER_PIXEL) * MM_PER_INCH / PIXELS_PER_INCH;
}

Simple visual representation of the problem: enter image description here

Pejman
  • 3,784
  • 4
  • 24
  • 33
  • Appears to be something like a "page foot" size setting, they seem to be added together. – Samuel Marchant Mar 30 '23 at 21:31
  • @SamuelMarchant I have checked, and there is no such thing as a 'page foot' there. Additionally, the extra space does not increase with every added page; rather, it increases every three pages, at least to the amount I have tested! – Pejman Mar 31 '23 at 08:40
  • @KJ Actually it is part of a large system, and almost everything is already done, and making changes at this stage wouldn't be a good idea. That's why I am focusing on getting this thing to work for now. – Pejman Mar 31 '23 at 08:44

0 Answers0