Dynamic Height size in footer using iText

I have an HTML code that I'm using in my report footer. However the height of this footer may vary according to the content of my HTML code. Is it possible to do some work to resize the height of my footer automatically according to the size of my code?

Footer.java

public class Footer extends PdfPageEventHelper {
    protected ElementList footer;
    public Footer(String html) throws IOException {
        footer = XMLWorkerHelper.parseToElementList(html, null);
    }
    @Override
    public void onEndPage(PdfWriter writer, Document document) {
        try {
            ColumnText ct = new ColumnText(writer.getDirectContent());

            // In my case this rectagle is resizeable height
            ct.setSimpleColumn(new Rectangle(36, 200, 559, 32));

            for (Element e : footer) {
                ct.addElement(e);
            }
            ct.go();
        } catch (DocumentException de) {
            throw new ExceptionConverter(de);
        }
    }
}

Upvotes: 2

Views: 1960

Answers (1)

mkl
mkl

Reputation: 95918

Your footer does not appear to have any dynamic parts, differing from page to page. In that case you can simply start by rendering that html to some throw-away PDF and measuring its dimensions, and then use these dimensions to set margins of the actual document you create.

You can implement this approach e.g. using a page event listener class like this:

public static class Footer extends PdfPageEventHelper {
    private final Rectangle boundingBox;
    private final List<Element> elements;
    private PdfTemplate template = null;
    private float blankAfter = 0;

    public Footer(String html, float width) throws DocumentException, IOException {
        this(XMLWorkerHelper.parseToElementList(html, null), width);
    }

    public Footer(List<Element> elements, float width) throws DocumentException, IOException {
        this.elements = elements;
        try (   OutputStream os = new NullOutputStream()    ) {
            Document document = new Document();
            PdfWriter writer = PdfWriter.getInstance(document, os);
            document.open();

            Rectangle bbox = new Rectangle(0, 0, width, 1000);
            float bottomLine = createTemplate(writer, bbox);
            boundingBox = new Rectangle(width, bbox.getTop() - bottomLine);
            template = null;

            writer.setPageEmpty(false);
            document.close();
        }
    }

    float createTemplate(PdfWriter writer, Rectangle boundingBox) throws DocumentException {
        template = writer.getDirectContent().createTemplate(10000, 10000);
        template.setBoundingBox(boundingBox);
        ColumnText columnText = new ColumnText(template);
        Rectangle bbox = template.getBoundingBox();
        columnText.setSimpleColumn(bbox.getLeft(), bbox.getBottom(), bbox.getRight(), bbox.getTop());
        for (Element element : elements) {
            columnText.addElement(element);
        }
        columnText.go();
        return columnText.getYLine() + columnText.getDescender();
    }

    void ensureTemplate(PdfWriter writer) throws DocumentException {
        if (template == null) {
            createTemplate(writer, boundingBox);
        }
    }

    public void setBottomMargin(Document document, float blankBefore, float blankAfter) {
        float marginBottom = boundingBox.getHeight() + blankBefore + blankAfter;
        document.setMargins(document.leftMargin(), document.rightMargin(), document.topMargin(), marginBottom);
        this.blankAfter = blankAfter;
    }

    @Override
    public void onEndPage(PdfWriter writer, Document document) {
        try {
            ensureTemplate(writer);

            Rectangle bbox = template.getBoundingBox();
            Rectangle pageSize = document.getPageSize();

            float x = pageSize.getLeft((pageSize.getWidth() - bbox.getWidth()) / 2f - bbox.getLeft());
            float y = pageSize.getBottom(blankAfter - bbox.getBottom());
            writer.getDirectContentUnder().addTemplate(template, x, y);
        } catch (DocumentException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        super.onEndPage(writer, document);
    }
}

(StaticFooter helper class)

You apply it like this:

Document document = new Document();
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(new File(RESULT_FOLDER, "StaticFooterShort.pdf")));

String html = "<p>Short Test Footer.</p>";
Footer footer = new Footer(html, document.right() - document.left());
writer.setPageEvent(footer);
footer.setBottomMargin(document, 10, 10);

document.open();

for (int i = 0; i < 200; i++) {
    document.add(new Paragraph("Lorem ipsum dolor sit amet, consetetur sadipscing elitr, ..."));
}

document.close();

(StaticFooter test testShortFooter)


PS: The NullOutputStream class I used is an Apache Commons IO helper but you can easily implement something similar if you don't want that extra dependency, simply implement an OutputStream that ignores all input.

Upvotes: 1

Related Questions