javaitextpdfstamper

itext setRotateContent Flag usage not clear


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.

ORIGINAL PDF enter image description here

With setRotateContent(false)

enter image description here

With setRotateContent(true)

enter image description here

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).


Solution

  • 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.