diff --git a/openpdf/src/main/java/com/lowagie/text/pdf/PdfSignatureAppearance.java b/openpdf/src/main/java/com/lowagie/text/pdf/PdfSignatureAppearance.java
index 99fe57988..94389653e 100755
--- a/openpdf/src/main/java/com/lowagie/text/pdf/PdfSignatureAppearance.java
+++ b/openpdf/src/main/java/com/lowagie/text/pdf/PdfSignatureAppearance.java
@@ -172,6 +172,7 @@ public class PdfSignatureAppearance {
private Certificate[] certChain;
private int render = SignatureRenderDescription;
private Image signatureGraphic = null;
+ private PdfImportedPage signaturePDF = null;
/**
* Holds value of property contact.
*/
@@ -311,6 +312,24 @@ public Image getSignatureGraphic() {
return signatureGraphic;
}
+ /**
+ * Gets the PDF page to render.
+ *
+ * @return the PDF page
+ */
+ public PdfImportedPage getSignaturePDF() {
+ return signaturePDF;
+ }
+
+ /**
+ * Check whether we already have a valid signature graphic (image or PDF).
+ *
+ * @return true if we have one valid signature graphic
+ */
+ public boolean hasValidSignatureGraphic() {
+ return (signatureGraphic != null || signaturePDF != null);
+ }
+
/**
* Sets the Image object to render when Render is set to
* SignatureRenderGraphicAndDescription
@@ -320,6 +339,21 @@ public Image getSignatureGraphic() {
*/
public void setSignatureGraphic(Image signatureGraphic) {
this.signatureGraphic = signatureGraphic;
+ this.signaturePDF = null;
+ }
+
+ /**
+ * Sets the PDF page to render as signature when Render is set to
+ * SignatureRenderGraphicAndDescription
+ *
+ * @param sigFile
+ * The PDF file to be rendered.
+ * @param pgnum
+ * The page number in the sigFile to be rendered (start from 1).
+ */
+ public void setSignaturePDF(PdfReader sigFile, int pgnum) {
+ this.signaturePDF = writer.getImportedPage(sigFile, pgnum);
+ this.signatureGraphic = null;
}
/**
@@ -632,7 +666,7 @@ public PdfTemplate getAppearance() throws DocumentException {
Rectangle signatureRect = null;
if (render == SignatureRenderNameAndDescription
- || (render == SignatureRenderGraphicAndDescription && this.signatureGraphic != null)) {
+ || (render == SignatureRenderGraphicAndDescription && hasValidSignatureGraphic())) {
// origin is the bottom-left
signatureRect = new Rectangle(MARGIN, MARGIN, rect.getWidth() / 2
- MARGIN, rect.getHeight() - MARGIN);
@@ -674,48 +708,9 @@ public PdfTemplate getAppearance() throws DocumentException {
ct2.go();
} else if (render == SignatureRenderGraphicAndDescription) {
- ColumnText ct2 = new ColumnText(t);
- ct2.setRunDirection(runDirection);
- ct2.setSimpleColumn(signatureRect.getLeft(), signatureRect.getBottom(),
- signatureRect.getRight(), signatureRect.getTop(), 0,
- Element.ALIGN_RIGHT);
-
- Image im = Image.getInstance(signatureGraphic);
- im.scaleToFit(signatureRect.getWidth(), signatureRect.getHeight());
-
- Paragraph p = new Paragraph();
- // must calculate the point to draw from to make image appear in middle
- // of column
- float x = 0;
- // experimentation found this magic number to counteract Adobe's
- // signature graphic, which
- // offsets the y co-ordinate by 15 units
- float y = -im.getScaledHeight() + 15;
-
- x = x + (signatureRect.getWidth() - im.getScaledWidth()) / 2;
- y = y - (signatureRect.getHeight() - im.getScaledHeight()) / 2;
- p.add(new Chunk(im, x
- + (signatureRect.getWidth() - im.getScaledWidth()) / 2, y, false));
- ct2.addElement(p);
- ct2.go();
+ renderSignatureGraphic(t, signatureRect);
} else if (this.render == SignatureRenderGraphic) {
- ColumnText ct2 = new ColumnText(t);
- ct2.setRunDirection(this.runDirection);
- ct2.setSimpleColumn(signatureRect.getLeft(), signatureRect.getBottom(), signatureRect.getRight(),
- signatureRect.getTop(), 0, Element.ALIGN_RIGHT);
-
- Image im = Image.getInstance(this.signatureGraphic);
- im.scaleToFit(signatureRect.getWidth(), signatureRect.getHeight());
-
- Paragraph p = new Paragraph(signatureRect.getHeight());
- // must calculate the point to draw from, to make image appear in the middle of the column
- float x = (signatureRect.getWidth() - im.getScaledWidth()) / 2f;
- float y = (signatureRect.getHeight() - im.getScaledHeight()) / 2f;
-
- p.add(new Chunk(im, x, y, false));
-
- ct2.addElement(p);
- ct2.go();
+ renderSignatureGraphic(t, signatureRect);
}
if (this.render != SignatureRenderGraphic) {
@@ -800,6 +795,38 @@ public PdfTemplate getAppearance() throws DocumentException {
return napp;
}
+ /**
+ * A helper to render signature graphic (PDF or image) to a give new layer
+ *
+ * @param t the new PDF object/layer to render on
+ */
+ private void renderSignatureGraphic(PdfTemplate t, Rectangle signatureRect) {
+ if (this.signatureGraphic != null) {
+ ColumnText ct2 = new ColumnText(t);
+ ct2.setRunDirection(this.runDirection);
+ ct2.setSimpleColumn(signatureRect.getLeft(), signatureRect.getBottom(), signatureRect.getRight(),
+ signatureRect.getTop(), 0, Element.ALIGN_RIGHT);
+
+ Image im = Image.getInstance(this.signatureGraphic);
+ im.scaleToFit(signatureRect.getWidth(), signatureRect.getHeight());
+
+ Paragraph p = new Paragraph(signatureRect.getHeight());
+ // must calculate the point to draw from, to make image appear in the middle of the column
+ float x = (signatureRect.getWidth() - im.getScaledWidth()) / 2f;
+ float y = (signatureRect.getHeight() - im.getScaledHeight()) / 2f;
+
+ p.add(new Chunk(im, x, y, false));
+
+ ct2.addElement(p);
+ ct2.go();
+ } else if (this.signaturePDF != null) {
+ float scale = Math.min(signatureRect.getWidth() / signaturePDF.getWidth(),
+ signatureRect.getHeight() / signaturePDF.getHeight());
+ t.addTemplate(signaturePDF, scale, 0, 0, scale, 0, 0);
+ }
+ }
+
+
/**
* Sets the digest/signature to an external calculated value.
*
@@ -1688,4 +1715,4 @@ public int read(byte[] b, int off, int len) throws IOException {
return -1;
}
}
-}
+}
\ No newline at end of file
diff --git a/openpdf/src/test/java/com/lowagie/text/pdf/PdfSignatureAppearanceTest.java b/openpdf/src/test/java/com/lowagie/text/pdf/PdfSignatureAppearanceTest.java
index c513a6867..61fe4b6db 100644
--- a/openpdf/src/test/java/com/lowagie/text/pdf/PdfSignatureAppearanceTest.java
+++ b/openpdf/src/test/java/com/lowagie/text/pdf/PdfSignatureAppearanceTest.java
@@ -5,6 +5,7 @@
import static org.junit.jupiter.api.Assertions.assertNotNull;
import com.lowagie.text.DocumentException;
+import com.lowagie.text.Image;
import com.lowagie.text.Rectangle;
import com.lowagie.text.Utilities;
import java.io.ByteArrayInputStream;
@@ -103,6 +104,8 @@ void visibleExternalSignature() throws DocumentException, IOException, NoSuchAlg
byte[] expectedDigestClose = null;
Calendar signDate = Calendar.getInstance();
+ Image sigImg = Image.getInstance(getClass().getClassLoader().getResource("GitHub-Mark-32px.png"));
+ PdfReader sigPdf = new PdfReader(getClass().getClassLoader().getResource("SimulatedBoldAndStrokeWidth.pdf"));
byte[] originalDocId = null;
PdfObject overrideFileId = new PdfLiteral("<123><123>".getBytes());
@@ -129,6 +132,17 @@ void visibleExternalSignature() throws DocumentException, IOException, NoSuchAlg
sap.setSignDate(signDate);
sap.setVisibleSignature(new Rectangle(100, 100), 1);
sap.setLayer2Text("Hello world");
+ if (i < 5) {
+ // Test image signature in the first half of the tests
+ sap.setSignatureGraphic(sigImg);
+ } else {
+ // Test PDF signature in the second half of the tests
+ if (i == 5) {
+ expectedDigestPreClose = null;
+ expectedDigestClose = null;
+ }
+ sap.setSignaturePDF(sigPdf, 1);
+ }
Map exc = new HashMap<>();
exc.put(PdfName.CONTENTS, 10);