I've created a standalone application with a lot of "test"
, "test\ntest"
, "test test test test"
, etc... cells. The result looks like this:

I have made several assumptions:
- I assume that cells are created using
String
values. Internally, this will result in a List
that contains a single Paragraph
. This Paragraph
will contain a single Text
object.
- I assume that no font was defined, that's why I introduce the default font (Helvetica).
- I assume that no leading was defined, hence I introduce a multiplied leading of
1
.
- I assume that no padding was defined, hence I introduce a padding of 1
This is my code:
import java.io.File;
import java.io.IOException;
import com.itextpdf.io.font.FontProgram;
import com.itextpdf.io.font.FontProgramFactory;
import com.itextpdf.kernel.font.PdfFont;
import com.itextpdf.kernel.font.PdfFontFactory;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.element.Cell;
import com.itextpdf.layout.element.Paragraph;
import com.itextpdf.layout.element.Table;
import com.itextpdf.layout.element.Text;
import com.itextpdf.layout.renderer.CellRenderer;
import com.itextpdf.layout.renderer.IRenderer;
public class FitCell {
public static final String[] TEST = {
"test",
"test test test test test test test",
"test test",
"test",
"test test test test\ntest test test test test test test test test test test",
"test",
"test",
"test",
"test\ntest\ntest\ntest",
"test",
"test",
"test",
"test",
"test",
"test",
"test",
"test",
"test\ntest",
"test",
"test",
"test",
"test",
"test",
"test",
"test test test test test test test test test test test test test test"
};
private class FitContentCellRenderer extends CellRenderer {
public FitContentCellRenderer(Cell modelElement) {
super(modelElement);
try {
// We assume that the Cell is created by passing a String
// This means that the Cell consists of one Paragraph
Paragraph p = (Paragraph)modelElement.getChildren().get(0);
// And that the Paragraph has one Text object
Text t = (Text)p.getChildren().get(0);
// Using the default font
FontProgram f = FontProgramFactory.createFont();
// We get the content from the Text object
String content = t.getText();
// Define a default font size (to make sure that you don't have text that is excessively big).
float fs = 100;
// Define a font size depending on the number of lines and the height
int[] fontBbox = f.getFontMetrics().getBbox();
int fh = (fontBbox[2] - fontBbox[1]);
float padding = 1;
modelElement.setPadding(padding);
float ch = modelElement.getHeight() - 2 * padding;
String text[] = content.split("\\r\\n|\\n|\\r");
fs = Math.min(fs, ch / (fh * text.length) * FontProgram.UNITS_NORMALIZATION);
// Loop over all the lines
PdfFont font = PdfFontFactory.createFont(f);
float cw = modelElement.getWidth().getValue() - 2 * padding;
for (String l : text) {
float w = font.getWidth(l, 1);
fs = Math.min(fs, cw / w);
}
p.setFontSize(fs);
p.setMultipliedLeading(1);
}
catch(IOException ioe) {
// occurs when font program can't be created; this never happens
}
}
@Override
public IRenderer getNextRenderer(){
return new FitContentCellRenderer(getModelElement());
}
}
private class FitContentCell extends Cell {
public FitContentCell() {
super();
this.setWidth(50);
}
@Override
protected IRenderer makeNewRenderer() {
return new FitContentCellRenderer(this);
}
}
public static final String DEST = "results/tables/cell_fit_content.pdf";
public static void main(String args[]) throws IOException {
File file = new File(DEST);
file.getParentFile().mkdirs();
new FitCell().createPdf(DEST);
}
public void createPdf(String dest) throws IOException {
PdfDocument pdf = new PdfDocument(new PdfWriter(dest));
Document document = new Document(pdf);
Table table = new Table(new float[]{1, 1, 1, 1, 1, 1, 1});
int testcount = 0;
for (int i = 0; i < 70; i++) {
if (testcount >= TEST.length) {
testcount = 0;
}
table.addCell(new FitContentCell().add(TEST[testcount++]).setHeight(20 + 10 * (i / 10)));
}
document.add(table);
document.close();
}
}
In this code, I change the behavior of the Cell
object in a subclass called FitCell
. The behavior of FitCell
is changed by overriding the CellRenderer
.
Actually, I'm not really changing the behavior of the renderer, but I'm changing some things the moment the renderer instance is created (before anything else happens). I define a padding for the cell, I define a font and a leading for the Paragraph
and I calculate the font size of the Paragraph
so that the text fits the cell. I first define a font size of 100 (which is huge), but none of the content will eventually have a font size of 100, because I first make sure that all the text fits the height of the cell; then I make sure that all the text fits the width of the cell.
The result is that all the text fits the cell.