📄 pdfsignatureappearance.java
字号:
public PdfTemplate getTopLayer() { if (frm == null) { frm = new PdfTemplate(writer); frm.setBoundingBox(rect); writer.addDirectTemplateSimple(frm, new PdfName("FRM")); } return frm; } /** * Gets the main appearance layer. * <p> * Consult <A HREF="http://partners.adobe.com/asn/developer/pdfs/tn/PPKAppearances.pdf">PPKAppearances.pdf</A> * for further details. * @return the main appearance layer * @throws DocumentException on error */ public PdfTemplate getAppearance() throws DocumentException { if (isInvisible()) { PdfTemplate t = new PdfTemplate(writer); t.setBoundingBox(new Rectangle(0, 0)); writer.addDirectTemplateSimple(t, null); return t; } if (app[0] == null) { PdfTemplate t = app[0] = new PdfTemplate(writer); t.setBoundingBox(new Rectangle(100, 100)); writer.addDirectTemplateSimple(t, new PdfName("n0")); t.setLiteral("% DSBlank\n"); } if (app[1] == null && !acro6Layers) { PdfTemplate t = app[1] = new PdfTemplate(writer); t.setBoundingBox(new Rectangle(100, 100)); writer.addDirectTemplateSimple(t, new PdfName("n1")); t.setLiteral(questionMark); } if (app[2] == null) { String text; if (layer2Text == null) { StringBuffer buf = new StringBuffer(); buf.append("Digitally signed by ").append(PdfPKCS7.getSubjectFields((X509Certificate)certChain[0]).getField("CN")).append('\n'); SimpleDateFormat sd = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss z"); buf.append("Date: ").append(sd.format(signDate.getTime())); if (reason != null) buf.append('\n').append("Reason: ").append(reason); if (location != null) buf.append('\n').append("Location: ").append(location); text = buf.toString(); } else text = layer2Text; PdfTemplate t = app[2] = new PdfTemplate(writer); t.setBoundingBox(rect); writer.addDirectTemplateSimple(t, new PdfName("n2")); if (image != null) { if (imageScale == 0) { t.addImage(image, rect.getWidth(), 0, 0, rect.getHeight(), 0, 0); } else { float usableScale = imageScale; if (imageScale < 0) usableScale = Math.min(rect.getWidth() / image.getWidth(), rect.getHeight() / image.getHeight()); float w = image.getWidth() * usableScale; float h = image.getHeight() * usableScale; float x = (rect.getWidth() - w) / 2; float y = (rect.getHeight() - h) / 2; t.addImage(image, w, 0, 0, h, x, y); } } Font font; if (layer2Font == null) font = new Font(); else font = new Font(layer2Font); float size = font.getSize(); Rectangle dataRect = null; Rectangle signatureRect = null; if (render == SignatureRenderNameAndDescription || (render == SignatureRenderGraphicAndDescription && this.signatureGraphic != null)) { // origin is the bottom-left signatureRect = new Rectangle( MARGIN, MARGIN, rect.getWidth() / 2 - MARGIN, rect.getHeight() - MARGIN); dataRect = new Rectangle( rect.getWidth() / 2 + MARGIN / 2, MARGIN, rect.getWidth() - MARGIN / 2, rect.getHeight() - MARGIN); if (rect.getHeight() > rect.getWidth()) { signatureRect = new Rectangle( MARGIN, rect.getHeight() / 2, rect.getWidth() - MARGIN, rect.getHeight()); dataRect = new Rectangle( MARGIN, MARGIN, rect.getWidth() - MARGIN, rect.getHeight() / 2 - MARGIN); } } else { dataRect = new Rectangle( MARGIN, MARGIN, rect.getWidth() - MARGIN, rect.getHeight() * (1 - TOP_SECTION) - MARGIN); } if (render == SignatureRenderNameAndDescription) { String signedBy = PdfPKCS7.getSubjectFields((X509Certificate)certChain[0]).getField("CN"); Rectangle sr2 = new Rectangle(signatureRect.getWidth() - MARGIN, signatureRect.getHeight() - MARGIN ); float signedSize = fitText(font, signedBy, sr2, -1, runDirection); ColumnText ct2 = new ColumnText(t); ct2.setRunDirection(runDirection); ct2.setSimpleColumn(new Phrase(signedBy, font), signatureRect.getLeft(), signatureRect.getBottom(), signatureRect.getRight(), signatureRect.getTop(), signedSize, Element.ALIGN_LEFT); 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(); } if (size <= 0) { Rectangle sr = new Rectangle(dataRect.getWidth(), dataRect.getHeight()); size = fitText(font, text, sr, 12, runDirection); } ColumnText ct = new ColumnText(t); ct.setRunDirection(runDirection); ct.setSimpleColumn(new Phrase(text, font), dataRect.getLeft(), dataRect.getBottom(), dataRect.getRight(), dataRect.getTop(), size, Element.ALIGN_LEFT); ct.go(); } if (app[3] == null && !acro6Layers) { PdfTemplate t = app[3] = new PdfTemplate(writer); t.setBoundingBox(new Rectangle(100, 100)); writer.addDirectTemplateSimple(t, new PdfName("n3")); t.setLiteral("% DSBlank\n"); } if (app[4] == null && !acro6Layers) { PdfTemplate t = app[4] = new PdfTemplate(writer); t.setBoundingBox(new Rectangle(0, rect.getHeight() * (1 - TOP_SECTION), rect.getRight(), rect.getTop())); writer.addDirectTemplateSimple(t, new PdfName("n4")); Font font; if (layer2Font == null) font = new Font(); else font = new Font(layer2Font); float size = font.getSize(); String text = "Signature Not Verified"; if (layer4Text != null) text = layer4Text; Rectangle sr = new Rectangle(rect.getWidth() - 2 * MARGIN, rect.getHeight() * TOP_SECTION - 2 * MARGIN); size = fitText(font, text, sr, 15, runDirection); ColumnText ct = new ColumnText(t); ct.setRunDirection(runDirection); ct.setSimpleColumn(new Phrase(text, font), MARGIN, 0, rect.getWidth() - MARGIN, rect.getHeight() - MARGIN, size, Element.ALIGN_LEFT); ct.go(); } int rotation = writer.reader.getPageRotation(page); Rectangle rotated = new Rectangle(rect); int n = rotation; while (n > 0) { rotated = rotated.rotate(); n -= 90; } if (frm == null) { frm = new PdfTemplate(writer); frm.setBoundingBox(rotated); writer.addDirectTemplateSimple(frm, new PdfName("FRM")); float scale = Math.min(rect.getWidth(), rect.getHeight()) * 0.9f; float x = (rect.getWidth() - scale) / 2; float y = (rect.getHeight() - scale) / 2; scale /= 100; if (rotation == 90) frm.concatCTM(0, 1, -1, 0, rect.getHeight(), 0); else if (rotation == 180) frm.concatCTM(-1, 0, 0, -1, rect.getWidth(), rect.getHeight()); else if (rotation == 270) frm.concatCTM(0, -1, 1, 0, 0, rect.getWidth()); frm.addTemplate(app[0], 0, 0); if (!acro6Layers) frm.addTemplate(app[1], scale, 0, 0, scale, x, y); frm.addTemplate(app[2], 0, 0); if (!acro6Layers) { frm.addTemplate(app[3], scale, 0, 0, scale, x, y); frm.addTemplate(app[4], 0, 0); } } PdfTemplate napp = new PdfTemplate(writer); napp.setBoundingBox(rotated); writer.addDirectTemplateSimple(napp, null); napp.addTemplate(frm, 0, 0); return napp; } /** * Fits the text to some rectangle adjusting the font size as needed. * @param font the font to use * @param text the text * @param rect the rectangle where the text must fit * @param maxFontSize the maximum font size * @param runDirection the run direction * @return the calculated font size that makes the text fit */ public static float fitText(Font font, String text, Rectangle rect, float maxFontSize, int runDirection) { try { ColumnText ct = null; int status = 0; if (maxFontSize <= 0) { int cr = 0; int lf = 0; char t[] = text.toCharArray(); for (int k = 0; k < t.length; ++k) { if (t[k] == '\n') ++lf; else if (t[k] == '\r') ++cr; } int minLines = Math.max(cr, lf) + 1; maxFontSize = Math.abs(rect.getHeight()) / minLines - 0.001f; } font.setSize(maxFontSize); Phrase ph = new Phrase(text, font); ct = new ColumnText(null); ct.setSimpleColumn(ph, rect.getLeft(), rect.getBottom(), rect.getRight(), rect.getTop(), maxFontSize, Element.ALIGN_LEFT); ct.setRunDirection(runDirection); status = ct.go(true); if ((status & ColumnText.NO_MORE_TEXT) != 0) return maxFontSize; float precision = 0.1f; float min = 0; float max = maxFontSize; float size = maxFontSize; for (int k = 0; k < 50; ++k) { //just in case it doesn't converge size = (min + max) / 2; ct = new ColumnText(null); font.setSize(size); ct.setSimpleColumn(new Phrase(text, font), rect.getLeft(), rect.getBottom(), rect.getRight(), rect.getTop(), size, Element.ALIGN_LEFT); ct.setRunDirection(runDirection); status = ct.go(true); if ((status & ColumnText.NO_MORE_TEXT) != 0) { if (max - min < size * precision) return size; min = size; } else max = size; } return size; } catch (Exception e) { throw new ExceptionConverter(e); } } /** * Sets the digest/signature to an external calculated value. * @param digest the digest. This is the actual signature * @param RSAdata the extra data that goes into the data tag in PKCS#7 * @param digestEncryptionAlgorithm the encryption algorithm. It may must be <CODE>null</CODE> if the <CODE>digest</CODE> * is also <CODE>null</CODE>. If the <CODE>digest</CODE> is not <CODE>null</CODE> * then it may be "RSA" or "DSA" */ public void setExternalDigest(byte digest[], byte RSAdata[], String digestEncryptionAlgorithm) { externalDigest = digest; externalRSAdata = RSAdata; this.digestEncryptionAlgorithm = digestEncryptionAlgorithm; } /** * Gets the signing reason. * @return the signing reason */ public String getReason() { return this.reason; } /** * Sets the signing reason. * @param reason the signing reason */ public void setReason(String reason) { this.reason = reason; } /** * Gets the signing location. * @return the signing location */ public String getLocation() { return this.location; } /** * Sets the signing location. * @param location the signing location */ public void setLocation(String location) { this.location = location; } /** * Returns the Cryptographic Service Provider that will sign the document. * @return provider the name of the provider, for example "SUN", * or <code>null</code> to use the default provider. */ public String getProvider() { return this.provider; } /** * Sets the Cryptographic Service Provider that will sign the document. * * @param provider the name of the provider, for example "SUN", or * <code>null</code> to use the default provider. */ public void setProvider(String provider) { this.provider = provider; } /** * Gets the private key. * @return the private key */ public java.security.PrivateKey getPrivKey() { return privKey; } /** * Gets the certificate chain. * @return the certificate chain */ public java.security.cert.Certificate[] getCertChain() { return this.certChain; } /** * Gets the certificate revocation list. * @return the certificate revocation list */ public java.security.cert.CRL[] getCrlList() {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -