How to define an offset for a PatternColor fill in iText?

J. Tec :

I am trying to add tiled diagonal watermarks to the pdf, but it seems that pattern fills in iText are always tiled from the bottom left of the page, meaning that the tiles at the top and right side of the page can be cut abruptly. Is there an option to tile from the top left or with an offset instead?

Here is a sample of the code:

List<String> watermarkLines = getWatermarkLines();
Rectangle watermarkRect = getWatermarkRect();

PdfContentByte over = stamper.getOverContent(1);
PdfPatternPainter painter = over.createPattern(watermarkRect.getWidth(), watermarkRect.getHeight();
for (int x = 0; x < watermarkLines.size(); x++) {
  AffineTransform trans = getWatermarkTransform(watermarkLines, x);
  ColumnText.showTextAligned(painter, 0, watermarkLines.get(x), (float) trans.getTranslateX(), (float) trans.getTranslateY(), 45f);
}

over.setColorFill(new PatternColor(painter));
over.rectangle(0, 0, pageSize.getWidth(), pageSize.getHeight());
over.fill();

I tried changing the x and y of the rectangle function to negative or positive values, but it seems that the watermark is still stamped in the pattern as if it was tiled from the bottom left, cutting it in the same place as before.

mkl :

First of, I cannot fathom which iText version you are using,

List<String> watermarkLines = getWatermarkLines();
...
ColumnText.showTextAligned(painter, 0, watermarkLines.get(x), (float) trans.getTranslateX(), (float) trans.getTranslateY(), 45f);

implies that the third parameter of the ColumnText.showTextAligned method you use is typed as String or Object. The iText 5 version I have at hand, though, requires a Phrase there. Below I'll show how to apply an offset with the current iText 5.5.13. You'll have to check whether it also works for your version.

Yes, you can apply an offset... in the pattern definition!

If instead of

PdfPatternPainter painter = over.createPattern(watermarkRect.getWidth(), watermarkRect.getHeight());

you create the pattern like this

PdfPatternPainter painter = over.createPattern(2 * watermarkRect.getWidth(), 2 * watermarkRect.getHeight(),
                                               watermarkRect.getWidth(), watermarkRect.getHeight());

you have the same step size of pattern application (watermarkRect.getWidth(), watermarkRect.getHeight()) but a canvas twice that width and twice that height to position you text on. By positioning the text with an offset, you effectively move the whole pattern by that offset.

E.g. if you calculate the offsets as

Rectangle pageSize = pdfReader.getCropBox(1);
float xOff = pageSize.getLeft();
float yOff = pageSize.getBottom() + ((int)pageSize.getHeight()) % ((int)watermarkRect.getHeight());

and draw the text using

ColumnText.showTextAligned(painter, 0, new Phrase(watermarkLines.get(x)), (float) trans.getTranslateX() + xOff, (float) trans.getTranslateY() + yOff, 45f);

the pattern should fill the page as if starting at the top left corner of the visible page.

You haven't supplied getWatermarkLines, getWatermarkRect, and getWatermarkTransform. If I use

static AffineTransform getWatermarkTransform(List<String> watermarkLines, int x) {
    return AffineTransform.getTranslateInstance(6 + 15*x, 6);
}

static Rectangle getWatermarkRect() {
    return new Rectangle(65, 50);
}

static List<String> getWatermarkLines() {
    return Arrays.asList("Test line 1", "Test line 2");
}

your original code for me creates a top left corner like this

screen shot original

and the code with the above offset creates one like this

screen shot with offset

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=110383&siteId=1