I am using pdfstamper to add the watermark to an existing pdf. When i keep the flag setRotateContent(true), the watermark comes at the right position but when i keep it false, watermark is misplaced. I cant share the code due to some restrictions.
I am sharing the cases.
With setRotateContent(false)
With setRotateContent(true)
So my question is how exactly does the setRotateContent() works. I have tried the Api page as well. But all the examples are with setRotateContent(false).
So my question is how exactly does the setRotateContent() works
As a bit of background you need to know that each PDF page contains an attribute Rotate which is specified as "The number of degrees by which the page shall be rotated clockwise when displayed or printed. The value shall be a multiple of 90. Default value: 0."
If you want to add something to a page which has a non-trivial Rotate value (i.e. a multiple of 360), therefore, there are two distinct situations:
While the former is trivial, you simply use the given coordinates and orientation, the latter requires you to read the Rotate value and calculate it into your coordinates and angles.
iText here tries to help you and, for setRotateContent(true)
, first adds a transformation to overcontent and undercontent, allowing you to simply go ahead choose coordinates and angles as if no page rotation was involved.
Seemingly the latter situation has been perceived to occur more often than the former. Thus, the default RotateContent
value is true
. In the former situation, therefore, you actually have to switch it off using setRotateContent(false)
.
As the question is how that works exactly: This is the method executed to initialize the undercontent and overcontent ByteBuffer
representation:
void applyRotation(PdfDictionary pageN, ByteBuffer out) {
if (!rotateContents)
return;
Rectangle page = reader.getPageSizeWithRotation(pageN);
int rotation = page.getRotation();
switch (rotation) {
case 90:
out.append(PdfContents.ROTATE90);
out.append(page.getTop());
out.append(' ').append('0').append(PdfContents.ROTATEFINAL);
break;
case 180:
out.append(PdfContents.ROTATE180);
out.append(page.getRight());
out.append(' ');
out.append(page.getTop());
out.append(PdfContents.ROTATEFINAL);
break;
case 270:
out.append(PdfContents.ROTATE270);
out.append('0').append(' ');
out.append(page.getRight());
out.append(PdfContents.ROTATEFINAL);
break;
}
}
(PdfStamperImp
)
with
static final byte ROTATE90[] = DocWriter.getISOBytes("0 1 -1 0 ");
static final byte ROTATE180[] = DocWriter.getISOBytes("-1 0 0 -1 ");
static final byte ROTATE270[] = DocWriter.getISOBytes("0 -1 1 0 ");
static final byte ROTATEFINAL[] = DocWriter.getISOBytes(" cm\n");
(PdfContents
)
PS: While the RotateContent
attribute controls whether or not these transformations are added to the overcontent and undercontent or not, there is a similar mechanism for annotations which cannot be disabled by that attribute, cf. this answer.