How to divide a page in N parts so we can fill each with a different source?

Tags: rectangleParagraphiText 7
Example
Example

So the first half of the page would be in English while the second part would be in French like this:

Example

In the future they might ask for 3rd language also, but maximum 3. Right now each page would have 2 blocks. How can I achieve this using iTextPDF in java?

Posted on StackOverflow on Feb 13, 2012 by IT ppl

If I understand your question correctly, you need to create something like this:

Example
Example

In this screen shot, you see the first part of the first book of Caesar's Commentaries on the Gallic War. Gallia omnia est divisa in partes tres, and so is each page in this document: the upper part shows the text in Latin, the middle part shows the text in English, the lower part shows the text in French. If you read the text, you'll discover that Belgians like me are considered being the bravest of all (although we aren't as civilized as one would wish). See three_parts.pdf if you want to take a look at the PDF.

This PDF was created with the ThreeParts example. In this example, I have 9 text files: liber1_1_la.txt, liber1_1_en.txt, liber1_1_fr.txt, liber1_2_la.txt, liber1_2_en.txt, liber1_2_fr.txt, liber1_3_la.txt, liber1_3_en.txt, and liber1_3_fr.txt.

Liber is the latin word for book, so all files are snippets from the first book, more specifically sections 1, 2, and 3, in Latin, English and French.

In my code, I loop over the different sections, and create a Paragraph object for each language:

PdfDocument pdfDoc = new PdfDocument(new PdfWriter(dest));
int firstPageNumber = 1;
for (int section = 0; section < 3; section++) {
    // latin
    addSection(pdfDoc, createParagraph(String.format("./src/test/resources/txt/liber1_%s_la.txt", section + 1)), firstPageNumber, 2);
    // english
    addSection(pdfDoc, createParagraph(String.format("./src/test/resources/txt/liber1_%s_en.txt", section + 1)), firstPageNumber, 1);
    // french
    addSection(pdfDoc, createParagraph(String.format("./src/test/resources/txt/liber1_%s_fr.txt", section + 1)), firstPageNumber, 0);
   firstPageNumber = pdfDoc.getNumberOfPages() + 1;
}

We are going to create Paragraphs like this:

public Paragraph createParagraph(String path) throws IOException {
    Paragraph p = new Paragraph();
    BufferedReader in = new BufferedReader(
            new InputStreamReader(new FileInputStream(path), "UTF-8"));
    StringBuffer buffer = new StringBuffer();
    String line = in.readLine();
    while (null != line) {
        buffer.append(line);
        line = in.readLine();
    }
    in.close();
    p.add(buffer.toString());
    return p;
}

And then use generated paragraphs in addSection() method:

public void addSection(PdfDocument pdfDoc, Paragraph paragraph, int pageNumber, int sectionNumber) throws IOException {
    LayoutResult layoutResult;
    ParagraphRenderer renderer = (ParagraphRenderer) paragraph.createRendererSubTree();
    renderer.setParent(new DocumentRenderer(new Document(pdfDoc)));
    while (((layoutResult = renderer.layout(new LayoutContext(new LayoutArea(pageNumber, new Rectangle(36, 36 + ((842 - 72) / 3) * sectionNumber, 523, (842 - 72) / 3)))))).getStatus() != LayoutResult.FULL) {
        if (pdfDoc.getNumberOfPages() < pageNumber) {
            pdfDoc.addNewPage();
        }
        layoutResult.getSplitRenderer().draw(new DrawContext(pdfDoc, new PdfCanvas(pdfDoc.getPage(pageNumber++)), false));
        renderer = (ParagraphRenderer) layoutResult.getOverflowRenderer();
    }
    if (pdfDoc.getNumberOfPages() < pageNumber) {
        pdfDoc.addNewPage();
    }
    renderer.draw(new DrawContext(pdfDoc, new PdfCanvas(pdfDoc.getPage(pageNumber)), false));
}

Here we’ve initialized ParagraphRenderer object and customized its LayoutArea according to the sectionNumber parameter. We check the status of LayoutResult and render the content to one or more pages until all the text from all sections is rendered.

As you can see, I also create a new page for every new section I start. This isn't really necessary, but depending on how the Latin text translated into English and French, you could end up with large discrepancies where section X of the Latin text starts on one page and the same section in English or French starts on another page. Hence my choice to start a new page, although it's not really necessary in this small proof of concept.

Click this link if you want to see how to answer this question in iText 5.