How to get the rendered dimensions of text?

Category: 
Tags: measure textfontsiText 7

I would like to find out information about the layout of text in a PdfPCell. I'm aware of BaseFont.getWidthPointKerned(), but I'm looking for more detailed information like:

  1. How many lines would a string need if rendered in a cell of a given width (say, 30pt)? What would the height in points of the PdfPCell be?
  2. Give me the prefix or suffix of a string that fits in a cell of a given width and height. That is, if I have to render the text "Today is a good day to die" in a specific font in a PdfPCell of width 12pt and height 20pt, what portion of the string would fit in the available space?
  3. Where does iText break a given string when asked to render it in a cell of a given width?

Posted on StackOverflow on Feb 28, 2014 by Kartick Vaddadi

iText uses the CellRenderer to render content to a cell. We measure the width of the characters and tests if they fit the available width. If not, the text is split. You can change the split behavior in different ways: by introducing hyphenation or by defining a custom split character.

I've written a small proof of concept to show how you could implement custom "truncation" behavior. See the TruncateTextInCell example.

I pass the long text "D2 is a cell with more content than we can fit into the cell." to the renderer of the cell.

In the renderer, I use a fancy algorithm: I want the text to be truncated in the middle and insert "..." at the place where I truncated the text.

PdfFont bf = getPropertyAsFont(Property.FONT);
float availableWidth = layoutContext.getArea().getBBox().getWidth() - paddingLeft - paddingRight - borderLeft - borderRight;
int contentLength = content.length();
int leftChar = 0;
int rightChar = contentLength - 1;
availableWidth -= bf.getWidth("...", 12);
while (leftChar < contentLength && rightChar != leftChar) {
    availableWidth -= bf.getWidth(content.charAt(leftChar), 12);
    if (availableWidth > 0)
        leftChar++;
    else {
        leftChar--; 
        break;
    }
    availableWidth -= bf.getWidth(content.charAt(rightChar), 12);
    if (availableWidth > 0)
        rightChar--;
    else{
        rightChar++;
        break;
    }
}
String newContent = content.substring(0, leftChar) + "..." + content.substring(rightChar);
Paragraph p = new Paragraph(newContent);
IRenderer pr = p.createRendererSubTree().setParent(this);
this.childRenderers.add(pr);
return super.layout(layoutContext);

As you can see, we get the available width and we check how many characters match, alternating between a character at the start and a character at the end of the content.

The result is shown in the resulting PDF: the content is truncated like this: "D2 is a c... the cell."

Your question about "how many lines" can be solved in a similar way. The CellRenderer will also help you with this. You can find more info about positioning in my answer to your other question: How to tell iText how to clip text to fit in a cell?"

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