1

I'm completely newbie to PDFBox and I'm having an issue I can't find the way to solve by the moment.

I get from my database a list of folder and documents located in those folders, I iterate over all these data to generate an index with active links to the correct folder/document path. (Imagine I have a root folder and I want to have a pdf index in that root with relative links to all folders and documents contained in it)

The main code looks like follows:

    try {
        PDDocument document = new PDDocument();
        PDPage page = new PDPage();

        document.addPage(page);

        PDFont font = PDType1Font.HELVETICA;


        PDPageContentStream contentStream = new PDPageContentStream(document, page);
        contentStream.beginText();
        contentStream.setFont(font, 12);
        contentStream.moveTextPositionByAmount(100, 700);
        contentStream.drawString("Índice " + expediente.getNombre());
        contentStream.endText();


        int i = 0;
        for (Folder currFol : root.getFolders()) {
            for (Document currDoc : currFol.getDocuments()) {
                i++;

                float x = 50;
                float y = 250;
                String text = currFol.getName() + "/" + currDoc.getName();
                float textWidth = font.getStringWidth(text) / 1000 * 12;

                PDAnnotationLink link = new PDAnnotationLink();
                PDGamma colourBlue = new PDGamma();
                colourBlue.setB(1);
                link.setColour(colourBlue);

                // add an action
                PDActionURI action = new PDActionURI();
                action.setURI(currFol.getName() + "/" + currDoc.getName());

                link.setAction(action);

                contentStream.beginText();
                contentStream.setFont(font, 12);
                contentStream.moveTextPositionByAmount(x, y);
                contentStream.drawString(text);
                contentStream.endText();

                PDRectangle position = new PDRectangle();
                position.setLowerLeftX(x);
                position.setLowerLeftY(y -(i* 5));
                position.setUpperRightX(x + textWidth);
                position.setUpperRightY(y + 50);
                link.setRectangle(position);

                page.getAnnotations().add(link);
            }
        }
        // Make sure that the content stream is closed:

        contentStream.close();

        document.save(output);

        document.close();
    } catch (Exception e) {
        e.printStackTrace();
    }

My problem here is that all elements are printed ovelaped, text and boxes are over each other and by the moment can't find out how to print correctly all links in a list formatted style to create the index.

Any idea or suggestion will be very apreciated.

I tried following some tutorials, with no succes by the moment, like http://www.programcreek.com/java-api-examples/index.php?api=org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationLink, http://www.massapi.com/class/pd/PDAnnotationLink.html .

I tried without PDRectangle, just the text link (as PDRectangle is present in all examples I found but I don't need it really)

Thank you,

  • 1
    @TilmanHausherr *relative to the previous position* - but the previous position is reset to 0,0 during `beginText`. As the OP only uses one `moveTextPositionByAmount` per text object, he can use it as if it were absolute. Actually that is part of his problem, he uses the same coordinates for all the text. – mkl Jun 03 '16 at 13:54
  • @mkl indeed, of course. I need more sleep. – Tilman Hausherr Jun 04 '16 at 13:23

1 Answers1

1

In your inner loop you always set x and y to the same values

float x = 50;
float y = 250;

which you don't change thereafter. Then you draw the respective text starting at x, y

contentStream.beginText();
contentStream.setFont(font, 12);
contentStream.moveTextPositionByAmount(x, y);
contentStream.drawString(text);
contentStream.endText();

Thus, you draw each entry starting at the same coordinates. So it is not surprising all the text overlaps.

Furthermore you set position and size of the links like this:

PDRectangle position = new PDRectangle();
position.setLowerLeftX(x);
position.setLowerLeftY(y -(i* 5));
position.setUpperRightX(x + textWidth);
position.setUpperRightY(y + 50);
link.setRectangle(position);

Thus, the upper y coordinate of each link is always y + 50, i.e. 300, and the lower y coordinate of the links moves down by 5 per iteration. So the vertical extent of your first link is contained in that of the second which in turn is contained in that of the third etc etc etc. Again no surprise that these annotations overlap.

Thus, this has nothing to do with being a PDFBox newbie but merely with getting one's coordinates right... ;)


How about something like this instead:

float x = 50;
float y = 650;

for (Folder currFol : root.getFolders()) {
    for (Document currDoc : currFol.getDocuments()) {
        String text = currFol.getName() + "/" + currDoc.getName();
        float textWidth = font.getStringWidth(text) / 1000.0 * 12;

        PDAnnotationLink link = new PDAnnotationLink();
        PDGamma colourBlue = new PDGamma();
        colourBlue.setB(1);
        link.setColour(colourBlue);

        // add an action
        PDActionURI action = new PDActionURI();
        action.setURI(currFol.getName() + "/" + currDoc.getName());

        link.setAction(action);

        contentStream.beginText();
        contentStream.setFont(font, 12);
        contentStream.moveTextPositionByAmount(x, y);
        contentStream.drawString(text);
        contentStream.endText();

        PDRectangle position = new PDRectangle();
        position.setLowerLeftX(x);
        position.setLowerLeftY(y - 3);
        position.setUpperRightX(x + textWidth);
        position.setUpperRightY(y + 12);
        link.setRectangle(position);

        page.getAnnotations().add(link);

        y -= 15;
    }
}
mkl
  • 90,588
  • 15
  • 125
  • 265
  • Hi @mkl, thank you for your answer, this works for me. You're right, Im a bit out of practice with these space coordinates concepts. I'll keep improving this solution to fit it into the rest of my document. – Raquel Garrido Jun 06 '16 at 06:03