How to draw a rectangle around multiline text?

Tags: ColumnTextrectanglecoordinate systemiText 5

I am trying to draw a rectangle around multi-line text in iText. I use this code to draw the text:

ColumnText ct = new ColumnText(cb);
Phrase phrase = new Phrase("Some String\nOther string etc...\n test");
ct.setSimpleColumn(myText......);
ct.addElement(phrase);
ct.go();
I know how to draw a rectangle, but I am not able to draw a rectangle outlining this text.

Posted on StackOverflow on Mar 13, 2012 by user2439522

It sounds as if you are missing only a single piece of the puzzle to meet your requirement. That piece is called getYLine().

Please take a look at the DrawRectangleAroundText example. This example draws the same paragraph twice. The first time, it adds a rectangle that probably looks like the solution you already have. The second time, it adds a rectangle the way you want it to look:

Screen shot
Screen shot

The first time, we add the text like this:

ColumnText ct = new ColumnText(cb);
ct.setSimpleColumn(120f, 500f, 250f, 780f);
Paragraph p = new Paragraph("This is a long paragraph that doesn't"
        + "fit the width we defined for the simple column of the" 
        + "ColumnText object, so it will be distributed over several"
        + "lines (and we don't know in advance how many).");
ct.addElement(p);
ct.go();

You define your column using the coordinates:

llx = 120;
lly = 500;
urx = 250;
ury = 780;

This is a rectangle with lower left corner (120, 500), a width of 130 and a height of 380. Hence you draw a rectangle like this:

cb.rectangle(120, 500, 130, 280);
cb.stroke();

Unfortunately, that rectangle is too big.

Now let's add the text once more at slightly different coordinates:

ct = new ColumnText(cb);
ct.setSimpleColumn(300f, 500f, 430f, 780f);
ct.addElement(p);
ct.go();

Instead of using (300, 500) as lower left corner for the rectangle, we ask the ct object for its current Y position using the getYLine() method:

float endPos = ct.getYLine() - 5;

As you can see, I subtract 5 user units, otherwise the bottom line of my rectangle will coincide with the baseline of the final line of text and that doesn't look very nice. Now I can use the endPos value to draw my rectangle like this:

cb.rectangle(300, endPos, 130, 780 - endPos);
cb.stroke();