iText - PDFAppearence issue

非 Y 不嫁゛ 提交于 2019-12-18 09:37:43

问题


We're using iText to put a text inside a signature placeholder in a PDF. We use a code snippet similar to this to define the Signature Appearence

PdfStamper stp = PdfStamper.createSignature(inputReader, os, '\0', tempFile2, true);
sap = stp.getSignatureAppearance();
sap.setVisibleSignature(placeholder);           
sap.setRenderingMode(PdfSignatureAppearance.RenderingMode.DESCRIPTION);
sap.setCertificationLevel(PdfSignatureAppearance.NOT_CERTIFIED);

Calendar cal = Calendar.getInstance();
sap.setSignDate(cal);
sap.setLayer2Text(text+"\n"+cal.getTime().toString());
sap.setReason(text+"\n"+cal.getTime().toString());      `

Everything works fine, but the signature text does not fill all the signature placeholder area as expected by us, but the area filled seems to have an height that is approximately the 70% of the available space.

As a result, sometimes especially if the length of the signature text is quite big, the signature text does not fit in the placeholder and the text is striped away.

Example of filled Signature:

I looked into the PdfSignatureAppearence class and I found this code snippet in the getApperance() method that is responsible of this behaviour and is invoked when

sap.setRenderingMode(PdfSignatureAppearance.RenderingMode.DESCRIPTION);

is being called

      else {
            dataRect = new Rectangle(
                    MARGIN,
                    MARGIN,
                    rect.getWidth() - MARGIN,
                    rect.getHeight() * (1 - TOP_SECTION) - MARGIN);
      }

I don't get the reason for that, because I expect that the text could use all the available placeholder height, with the proper margin.

Is there any way to bypass this behaviour?

We are using iText 5.4.2, but also newer version contains same code snippet so I expect that the behaviour will be same.


回答1:


As @JJ. already commented,

TOP_SECTION is connected with acro6layers rendering and the code [determining the datarect in pure DESCRIPTION mode] does not take into account the value of the acro6layer flag.

Unless one wants to fix this in the iText 5 code itself, the easiest way to make one's description use the whole signature space is to construct the layer 2 appearance oneself.

To do so one merely has to retrieve a PdfTemplate from PdfSignatureAppearance.getLayer(2) and fill it as desired after one has called PdfSignatureAppearance.setVisibleSignature. The PdfSignatureAppearance remembers that you already have retrieved the layer 2 and doesn't change it anymore.

For the case at hand we essentially copy the PdfSignatureAppearance.getAppearance code for generating layer 2 in pure DESCRIPTION mode, merely correcting the code determining the datarect:

PdfSignatureAppearance appearance = ...;
[...]
appearance.setVisibleSignature(new Rectangle(36, 748, 144, 780), 1, "sig");

PdfTemplate layer2 = appearance.getLayer(2);
String text = "We're using iText to put a text inside a signature placeholder in a PDF. "
        + "We use a code snippet similar to this to define the Signature Appearence.\n"
        + "Everything works fine, but the signature text does not fill all the signature "
        + "placeholder area as expected by us, but the area filled seems to have an height "
        + "that is approximately the 70% of the available space.\n"
        + "As a result, sometimes especially if the length of the signature text is quite "
        + "big, the signature text does not fit in the placeholder and the text is striped "
        + "away.";
Font font = new Font();
float size = font.getSize();
final float MARGIN = 2;
Rectangle dataRect = new Rectangle(
        MARGIN,
        MARGIN,
        appearance.getRect().getWidth() - MARGIN,
        appearance.getRect().getHeight() - MARGIN);
if (size <= 0) {
    Rectangle sr = new Rectangle(dataRect.getWidth(), dataRect.getHeight());
    size = ColumnText.fitText(font, text, sr, 12, appearance.getRunDirection());
}
ColumnText ct = new ColumnText(layer2);
ct.setRunDirection(appearance.getRunDirection());
ct.setSimpleColumn(new Phrase(text, font), dataRect.getLeft(), dataRect.getBottom(), dataRect.getRight(), dataRect.getTop(), size, Element.ALIGN_LEFT);
ct.go();

(CreateSignature.java test signWithCustomLayer2)

(As description text I used some paragraphs from the question body.)

The result:

By adapting the MARGIN value in the code above, one can even use more are. As that can result in the text touching the border, though, that might not be really beautiful.


As an aside:

if the length of the signature text is quite big, the signature text does not fit in the placeholder and the text is striped away.

If you initialize the size variable above with a non-positive value, the code in the if (size <= 0) block will calculate a font size which allows all of the text to fit into the signature rectangle. This does happen in the code above as new Font() returns a font with a size of UNDEFINED which is a constant -1.



来源:https://stackoverflow.com/questions/45062602/itext-pdfappearence-issue

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!