How to tell iText how to clip text to fit in a cell?

Category: 
Tags: tablescell heightclippingiText 7

When I call setFixedHeight() on a PdfPCell, and add more text than fits in the given height, iText seems to print the prefix of the string which fits.

Can I control this clipping algorithm? For example:

  1. Print a suffix of the string rather than a prefix.
  2. Mark a substring of the string as not to be removed. This is with footnote references. If I add text saying "Hello World [1]", the [1] is a reference to a footnote and should not be removed. It's okay to remove the other characters of the string, like "World".
  3. When there are multiple words in the string, iText seems to eliminate a word that doesn't fit, while I would like it partially printed. That is, if the string is "Hello World", and the cell has room only for "Hello Wo...", I would like that to be printed, rather than just "Hello", as iText prints.
  4. Rather than printing characters in their entirety, print only part of them. Imagine printing the text to a PNG and chopping off the top and/or bottom part of the PNG to fit it in the space available. For example, notice that the top line and the bottom line are partially clipped here:

Clipped content in a cell

Are any of these possible? Does iText give me any control over how text is clipped? Thanks.

Posted on StackOverflow on Feb 28, 2014 by Kartick Vaddadi

I have written a proof of concept, ClipCenterCellContent, where we try to fit the text "D2 is a cell with more content than we can fit into the cell." in a cell that is too small.

We add the content using a CellRenderer and overriding the draw() method.

In iText 7 you would need to manipulate with table renderer a bit:

IRenderer pr = content.createRendererSubTree().setParent(this);
LayoutResult textArea = pr.layout(new LayoutContext(
                new LayoutArea(0, new Rectangle(getOccupiedAreaBBox().getWidth(), 1000))));

A renderer is created, and layout() is called for an area which is clearly big enough to fit the cell, afterwards you can get the actual occupied area of a cell:

float spaceneeded = textArea.getOccupiedArea().getBBox().getHeight();
System.out.println(String.format("The content requires %s pt whereas the height is %s pt.",
                spaceneeded, getOccupiedAreaBBox().getHeight()));

We now know the needed height and we can add the content using an offset:

float offset = (getOccupiedAreaBBox().getHeight() - textArea.getOccupiedArea().getBBox().getHeight()) / 2;
System.out.println(String.format("The difference is %s pt; we'll need an offset of %s pt.",
                -2f * offset, offset));
PdfFormXObject xObject = new PdfFormXObject(new Rectangle(getOccupiedAreaBBox().getWidth(),
                getOccupiedAreaBBox().getHeight()));
Canvas layoutCanvas = new Canvas(new PdfCanvas(xObject, drawContext.getDocument()), drawContext.getDocument(),
                new Rectangle(0, offset, getOccupiedAreaBBox().getWidth(), spaceneeded));
layoutCanvas.add(content);
drawContext.getCanvas().addXObject(xObject, occupiedArea.getBBox().getLeft(), occupiedArea.getBBox().getBottom());

In this case, I used a PdfFormXObject to clip the content.

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