How to add a background image to a cell?
I want to create a document which contains a table with cells with the same background image and text.
I have the following requirements:
I want to create a document which contains one table. Inside that table, there are cells.
I want to make each cell with specific height.
each cell have the same background image.
I want to put a text in front the image in the position I want inside the cell. For example: top left of the cell, bottom right of the cell.
Posted on StackOverflow on Jul 1, 2015 by lasheul
In other words: you want something like this: position_content_in_cell.pdf
There is more than one way to do this. Note that PdfPCell
class does not exist in iText 7 anymore. You should use Cell
instead. To add your own custom image and text you need to extend CellRenderer
and override draw()
method:
private class ImageAndPositionRenderer extends CellRenderer {
private Image img;
private String content;
private POSITION position;
public ImageAndPositionRenderer(Cell modelElement, Image img, String content, POSITION position) {
super(modelElement);
this.img = img;
this.content = content;
this.position = position;
}
@Override
public void draw(DrawContext drawContext) {
super.draw(drawContext);
img.scaleToFit(getOccupiedAreaBBox().getWidth(), getOccupiedAreaBBox().getHeight());
img.getProperty(Property.HORIZONTAL_SCALING);
drawContext.getCanvas().addXObject(img.getXObject(),
getOccupiedAreaBBox().getX() +
(getOccupiedAreaBBox().getWidth()
- img.getImageWidth() * (float) img.getProperty(Property.HORIZONTAL_SCALING)) / 2,
getOccupiedAreaBBox().getY() +
(getOccupiedAreaBBox().getHeight()
- img.getImageHeight() * (float) img.getProperty(Property.VERTICAL_SCALING)) / 2,
img.getImageWidth() * (float) img.getProperty(Property.HORIZONTAL_SCALING));
drawContext.getCanvas().stroke();
Paragraph p = new Paragraph(content);
Leading leading = p.getDefaultProperty(Property.LEADING);
Float defaultFontSize = new DocumentRenderer(new Document(drawContext.getDocument())).getPropertyAsFloat(Property.FONT_SIZE);
float x;
float y;
TextAlignment alignment;
switch (position) {
case TOP_LEFT:
x = getOccupiedAreaBBox().getLeft() + 3;
y = getOccupiedAreaBBox().getTop() - defaultFontSize * leading.getValue();
alignment = TextAlignment.LEFT;
break;
case TOP_RIGHT:
x = getOccupiedAreaBBox().getRight() - 3;
y = getOccupiedAreaBBox().getTop() - defaultFontSize * leading.getValue();
alignment = TextAlignment.RIGHT;
break;
case BOTTOM_LEFT:
x = getOccupiedAreaBBox().getLeft() + 3;
y = getOccupiedAreaBBox().getBottom() + 3;
alignment = TextAlignment.LEFT;
break;
case BOTTOM_RIGHT:
x = getOccupiedAreaBBox().getRight() - 3;
y = getOccupiedAreaBBox().getBottom() + 3;
alignment = TextAlignment.RIGHT;
break;
default:
x = 0;
y = 0;
alignment = TextAlignment.CENTER;
}
new Canvas(drawContext.getCanvas(), drawContext.getDocument(), getOccupiedAreaBBox()).showTextAligned(p, x, y, alignment);
}
}
So we’ve set the rules too add an image and draw some text inside the cell. We’ll use ImageAndPositionRenderer
in setNextRenderer()
method like this:
cell1.setNextRenderer(new ImageAndPositionRenderer(cell1,
new Image(ImageDataFactory.create(IMG)), "Top left", POSITION.TOP_LEFT));
Where cell1
is a Cell
object. Don’t forget to set the specific height for each cell:
cell1.setHeight(50);
Normally, I would write this code in a more efficient way, but I order the code lines in a way so that they reflect your requirements 1, 2, 3 and 4 literally.
OK, but how can I stretch the image?
Please check the PositionContentInCell example for the full code. As you see, we’ve used scaleToFit()
method to stretch the image. Without this line, you’ll get the following result:
How can I position the image inside a cell using x
and y
coordinates
That required an extra example: PositionContentInCell2.
Instead of using the POSITION
enumeration, you asked if it was possible to pass x
and y
values. You could do that, but you probably won't always know the width and the height of the cells, so why not define percentages such as wPct
and hPct
, along with an alignment:
private class ImageAndPositionRenderer extends CellRenderer {
private Image img;
private String content;
private TextAlignment alignment;
private float wPct;
private float hPct;
public ImageAndPositionRenderer(Cell modelElement, float wPct, float hPct,
Image img, String content, TextAlignment alignment) {
super(modelElement);
this.img = img;
this.content = content;
this.alignment = alignment;
this.wPct = wPct;
this.hPct = hPct;
}
@Override
public void draw(DrawContext drawContext) {
super.draw(drawContext);
drawContext.getCanvas().addXObject(img.getXObject(), getOccupiedAreaBBox());
drawContext.getCanvas().stroke();
float x = getOccupiedAreaBBox().getX() + wPct * getOccupiedAreaBBox().getWidth();
float y = getOccupiedAreaBBox().getY() + hPct * (getOccupiedAreaBBox().getHeight() - drawContext.getCanvas().getGraphicsState().getLeading());
new Document(drawContext.getDocument()).showTextAligned(content, x, y, alignment);
}
}
Now you can add these events like this:
cell1.setNextRenderer(new ImageAndPositionRenderer(cell1, 0, 1,
new Image(ImageDataFactory.create(IMG)), "Top left", TextAlignment.LEFT));
Click How to add a background image to a cell? if you want to see how to answer this question in iText 5.