How to draw a line every 25 words?

Category: 
Tags: TextiText 7

I create a PDF using iText. The content consists of text and I need to draw a line to delimit this text every 25 words as shown in the following image:

Desired result

I'm aware there's a way of that I can extract text and text positions once I have a finished PDF, but considering I'm writing the text to the PDF file, I guess there could be a way of adding these lines during the creation process without really having to find the text position, right?

Posted on StackOverflow on Feb 25, 2015 by Matias Bello

Please take a look at the Every25Words example. In that example, I read a text file into a String with the readFile() method. I then split the text into words based on the occurrence of spaces, and I add each word one by one:

public void manipulatePdf(String dest) throws IOException {
    PdfDocument pdfDoc = new PdfDocument(new PdfWriter(dest));
    Document doc = new Document(pdfDoc);
    String[] words = readFile().split("\\s+");
    Paragraph paragraph = new Paragraph();
    Text text = null;
    int i = 0;
    for (String word : words) {
        if (text != null) {
            paragraph.add(" ");
        }
        text = new Text(word);
        text.setNextRenderer(new Word25TextRenderer(text, ++i));
        paragraph.add(text);
    }
    doc.add(paragraph);
    doc.close();
}

As you see we define a Word25TextRenderer to catch every 25th word and draw a dashed line. It happens through extending a TextRenderer class:

private class Word25TextRenderer extends TextRenderer {
    private int count = 0;

    public Word25TextRenderer(Text textElement, int count) {
        super(textElement);
        this.count = count;
    }

    @Override
    public void draw(DrawContext drawContext) {
        super.draw(drawContext);
        if (0 == count % 25) {
            Rectangle rect = getOccupiedAreaBBox();
            int pageNumber = getOccupiedArea().getPageNumber();
            PdfCanvas canvas = drawContext.getCanvas();
            canvas.saveState()
                    .setLineDash(5, 5)
                    .moveTo(drawContext.getDocument().getPage(pageNumber).getPageSize().getLeft(), rect.getBottom())
                    .lineTo(rect.getRight(), rect.getBottom())
                    .lineTo(rect.getRight(), rect.getTop())
                    .lineTo(drawContext.getDocument().getDefaultPageSize().getRight(), rect.getTop())
                    .stroke()
                    .restoreState();
        }
    }
}

Do you see what we do between the saveState() and restoreState() methods? We define a dash pattern, we move to the left of the page, we construct a path to the right of the word, then we draw a short upwards line, to finish the path with a line to the right. Once the path is constructed, we stroke the line. To get the area occupied by the current word we use getOccupiedAreaBBox() method and store the result to the Rectangle variable.

This draw() method will be triggered every time a Text is added on which we used the setNextRenderer() method.

This is what the result looks like every25words.pdf:

Screen shot of result
Screen shot of result

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