Search in sources :

Example 1 with PDSignatureField

use of org.apache.pdfbox.pdmodel.interactive.form.PDSignatureField in project pdfbox by apache.

the class PDDocument method addSignature.

/**
 * This will add a signature to the document. If the 0-based page number in the options
 * parameter is smaller than 0 or larger than max, the nearest valid page number will be used
 * (i.e. 0 or max) and no exception will be thrown.
 *
 * @param sigObject is the PDSignatureField model
 * @param signatureInterface is an interface which provides signing capabilities
 * @param options signature options
 * @throws IOException if there is an error creating required fields
 */
public void addSignature(PDSignature sigObject, SignatureInterface signatureInterface, SignatureOptions options) throws IOException {
    // Reserve content
    // We need to reserve some space for the signature. Some signatures including
    // big certificate chain and we need enough space to store it.
    int preferredSignatureSize = options.getPreferredSignatureSize();
    if (preferredSignatureSize > 0) {
        sigObject.setContents(new byte[preferredSignatureSize]);
    } else {
        sigObject.setContents(new byte[SignatureOptions.DEFAULT_SIGNATURE_SIZE]);
    }
    // Reserve ByteRange, will be overwritten in COSWriter
    sigObject.setByteRange(RESERVE_BYTE_RANGE);
    signInterface = signatureInterface;
    // Create SignatureForm for signature and append it to the document
    // Get the first valid page
    int pageCount = getNumberOfPages();
    if (pageCount == 0) {
        throw new IllegalStateException("Cannot sign an empty document");
    }
    int startIndex = Math.min(Math.max(options.getPage(), 0), pageCount - 1);
    PDPage page = getPage(startIndex);
    // Get the AcroForm from the Root-Dictionary and append the annotation
    PDDocumentCatalog catalog = getDocumentCatalog();
    PDAcroForm acroForm = catalog.getAcroForm();
    catalog.getCOSObject().setNeedToBeUpdated(true);
    if (acroForm == null) {
        acroForm = new PDAcroForm(this);
        catalog.setAcroForm(acroForm);
    } else {
        acroForm.getCOSObject().setNeedToBeUpdated(true);
    }
    PDSignatureField signatureField = null;
    if (!(acroForm.getCOSObject().getDictionaryObject(COSName.FIELDS) instanceof COSArray)) {
        acroForm.getCOSObject().setItem(COSName.FIELDS, new COSArray());
    } else {
        COSArray fieldArray = (COSArray) acroForm.getCOSObject().getDictionaryObject(COSName.FIELDS);
        fieldArray.setNeedToBeUpdated(true);
        signatureField = findSignatureField(acroForm.getFieldIterator(), sigObject);
    }
    if (signatureField == null) {
        signatureField = new PDSignatureField(acroForm);
        // append the signature object
        signatureField.setValue(sigObject);
        // backward linking
        signatureField.getWidgets().get(0).setPage(page);
    } else {
        sigObject.getCOSObject().setNeedToBeUpdated(true);
    }
    // TODO This "overwrites" the settings of the original signature field which might not be intended by the user
    // better make it configurable (not all users need/want PDF/A but their own setting):
    // to conform PDF/A-1 requirement:
    // The /F key's Print flag bit shall be set to 1 and
    // its Hidden, Invisible and NoView flag bits shall be set to 0
    signatureField.getWidgets().get(0).setPrinted(true);
    // Set the AcroForm Fields
    List<PDField> acroFormFields = acroForm.getFields();
    acroForm.getCOSObject().setDirect(true);
    acroForm.setSignaturesExist(true);
    acroForm.setAppendOnly(true);
    boolean checkFields = checkSignatureField(acroForm.getFieldIterator(), signatureField);
    if (checkFields) {
        signatureField.getCOSObject().setNeedToBeUpdated(true);
    } else {
        acroFormFields.add(signatureField);
    }
    // Get the object from the visual signature
    COSDocument visualSignature = options.getVisualSignature();
    // Distinction of case for visual and non-visual signature
    if (visualSignature == null) {
        prepareNonVisibleSignature(signatureField);
        return;
    }
    prepareVisibleSignature(signatureField, acroForm, visualSignature);
    // Create Annotation / Field for signature
    List<PDAnnotation> annotations = page.getAnnotations();
    // Make /Annots a direct object to avoid problem if it is an existing indirect object:
    // it would not be updated in incremental save, and if we'd set the /Annots array "to be updated"
    // while keeping it indirect, Adobe Reader would claim that the document had been modified.
    page.setAnnotations(annotations);
    // take care that page and acroforms do not share the same array (if so, we don't need to add it twice)
    if (!(annotations instanceof COSArrayList && acroFormFields instanceof COSArrayList && ((COSArrayList<?>) annotations).toList().equals(((COSArrayList<?>) acroFormFields).toList()) && checkFields)) {
        PDAnnotationWidget widget = signatureField.getWidgets().get(0);
        // use check to prevent the annotation widget from appearing twice
        if (checkSignatureAnnotation(annotations, widget)) {
            widget.getCOSObject().setNeedToBeUpdated(true);
        } else {
            annotations.add(widget);
        }
    }
    page.getCOSObject().setNeedToBeUpdated(true);
}
Also used : PDField(org.apache.pdfbox.pdmodel.interactive.form.PDField) PDAnnotation(org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotation) COSDocument(org.apache.pdfbox.cos.COSDocument) PDAcroForm(org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm) Point(java.awt.Point) COSArrayList(org.apache.pdfbox.pdmodel.common.COSArrayList) COSArray(org.apache.pdfbox.cos.COSArray) PDAnnotationWidget(org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationWidget) PDSignatureField(org.apache.pdfbox.pdmodel.interactive.form.PDSignatureField)

Example 2 with PDSignatureField

use of org.apache.pdfbox.pdmodel.interactive.form.PDSignatureField in project pdfbox by apache.

the class PDFTemplateCreator method buildPDF.

/**
 * Build a PDF with a visible signature step by step, and return it as a stream.
 *
 * @param properties
 * @return InputStream
 * @throws IOException
 */
public InputStream buildPDF(PDVisibleSignDesigner properties) throws IOException {
    LOG.info("pdf building has been started");
    PDFTemplateStructure pdfStructure = pdfBuilder.getStructure();
    // we create array of [Text, ImageB, ImageC, ImageI]
    pdfBuilder.createProcSetArray();
    // create page
    pdfBuilder.createPage(properties);
    PDPage page = pdfStructure.getPage();
    // create template
    pdfBuilder.createTemplate(page);
    PDDocument template = pdfStructure.getTemplate();
    // create /AcroForm
    pdfBuilder.createAcroForm(template);
    PDAcroForm acroForm = pdfStructure.getAcroForm();
    // AcroForm contains signature fields
    pdfBuilder.createSignatureField(acroForm);
    PDSignatureField pdSignatureField = pdfStructure.getSignatureField();
    // create signature
    // TODO
    // The line below has no effect with the CreateVisibleSignature example.
    // The signature field is needed as a "holder" for the /AP tree,
    // but the /P and /V PDSignatureField entries are ignored by PDDocument.addSignature
    pdfBuilder.createSignature(pdSignatureField, page, "");
    // that is /AcroForm/DR entry
    pdfBuilder.createAcroFormDictionary(acroForm, pdSignatureField);
    // create AffineTransform
    pdfBuilder.createAffineTransform(properties.getTransform());
    AffineTransform transform = pdfStructure.getAffineTransform();
    // rectangle, formatter, image. /AcroForm/DR/XObject contains that form
    pdfBuilder.createSignatureRectangle(pdSignatureField, properties);
    pdfBuilder.createFormatterRectangle(properties.getFormatterRectangleParameters());
    PDRectangle bbox = pdfStructure.getFormatterRectangle();
    pdfBuilder.createSignatureImage(template, properties.getImage());
    // create form stream, form and  resource.
    pdfBuilder.createHolderFormStream(template);
    PDStream holderFormStream = pdfStructure.getHolderFormStream();
    pdfBuilder.createHolderFormResources();
    PDResources holderFormResources = pdfStructure.getHolderFormResources();
    pdfBuilder.createHolderForm(holderFormResources, holderFormStream, bbox);
    // that is /AP entry the appearance dictionary.
    pdfBuilder.createAppearanceDictionary(pdfStructure.getHolderForm(), pdSignatureField);
    // inner form stream, form and resource (hlder form containts inner form)
    pdfBuilder.createInnerFormStream(template);
    pdfBuilder.createInnerFormResource();
    PDResources innerFormResource = pdfStructure.getInnerFormResources();
    pdfBuilder.createInnerForm(innerFormResource, pdfStructure.getInnerFormStream(), bbox);
    PDFormXObject innerForm = pdfStructure.getInnerForm();
    // inner form must be in the holder form as we wrote
    pdfBuilder.insertInnerFormToHolderResources(innerForm, holderFormResources);
    // Image form is in this structure: /AcroForm/DR/FRM/Resources/XObject/n2
    pdfBuilder.createImageFormStream(template);
    PDStream imageFormStream = pdfStructure.getImageFormStream();
    pdfBuilder.createImageFormResources();
    PDResources imageFormResources = pdfStructure.getImageFormResources();
    pdfBuilder.createImageForm(imageFormResources, innerFormResource, imageFormStream, bbox, transform, pdfStructure.getImage());
    pdfBuilder.createBackgroundLayerForm(innerFormResource, bbox);
    // now inject procSetArray
    pdfBuilder.injectProcSetArray(innerForm, page, innerFormResource, imageFormResources, holderFormResources, pdfStructure.getProcSet());
    COSName imageFormName = pdfStructure.getImageFormName();
    COSName imageName = pdfStructure.getImageName();
    COSName innerFormName = pdfStructure.getInnerFormName();
    // now create Streams of AP
    pdfBuilder.injectAppearanceStreams(holderFormStream, imageFormStream, imageFormStream, imageFormName, imageName, innerFormName, properties);
    pdfBuilder.createVisualSignature(template);
    pdfBuilder.createWidgetDictionary(pdSignatureField, holderFormResources);
    InputStream in = getVisualSignatureAsStream(pdfStructure.getVisualSignature());
    LOG.info("stream returning started, size= " + in.available());
    // we must close the document
    template.close();
    // return result of the stream
    return in;
}
Also used : PDPage(org.apache.pdfbox.pdmodel.PDPage) COSName(org.apache.pdfbox.cos.COSName) ByteArrayInputStream(java.io.ByteArrayInputStream) InputStream(java.io.InputStream) PDDocument(org.apache.pdfbox.pdmodel.PDDocument) AffineTransform(java.awt.geom.AffineTransform) PDResources(org.apache.pdfbox.pdmodel.PDResources) PDFormXObject(org.apache.pdfbox.pdmodel.graphics.form.PDFormXObject) PDRectangle(org.apache.pdfbox.pdmodel.common.PDRectangle) PDAcroForm(org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm) PDSignatureField(org.apache.pdfbox.pdmodel.interactive.form.PDSignatureField) PDStream(org.apache.pdfbox.pdmodel.common.PDStream)

Example 3 with PDSignatureField

use of org.apache.pdfbox.pdmodel.interactive.form.PDSignatureField in project pdfbox by apache.

the class PDVisibleSigBuilder method createSignatureField.

@Override
public void createSignatureField(PDAcroForm acroForm) throws IOException {
    PDSignatureField sf = new PDSignatureField(acroForm);
    pdfStructure.setSignatureField(sf);
    LOG.info("Signature field has been created");
}
Also used : PDSignatureField(org.apache.pdfbox.pdmodel.interactive.form.PDSignatureField)

Example 4 with PDSignatureField

use of org.apache.pdfbox.pdmodel.interactive.form.PDSignatureField in project pdfbox by apache.

the class CreateEmptySignatureForm method main.

public static void main(String[] args) throws IOException {
    // Create a new document with an empty page.
    try (PDDocument document = new PDDocument()) {
        PDPage page = new PDPage(PDRectangle.A4);
        document.addPage(page);
        // Adobe Acrobat uses Helvetica as a default font and
        // stores that under the name '/Helv' in the resources dictionary
        PDFont font = PDType1Font.HELVETICA;
        PDResources resources = new PDResources();
        resources.put(COSName.getPDFName("Helv"), font);
        // Add a new AcroForm and add that to the document
        PDAcroForm acroForm = new PDAcroForm(document);
        document.getDocumentCatalog().setAcroForm(acroForm);
        // Add and set the resources and default appearance at the form level
        acroForm.setDefaultResources(resources);
        // Acrobat sets the font size on the form level to be
        // auto sized as default. This is done by setting the font size to '0'
        String defaultAppearanceString = "/Helv 0 Tf 0 g";
        acroForm.setDefaultAppearance(defaultAppearanceString);
        // --- end of general AcroForm stuff ---
        // Create empty signature field, it will get the name "Signature1"
        PDSignatureField signatureField = new PDSignatureField(acroForm);
        PDAnnotationWidget widget = signatureField.getWidgets().get(0);
        PDRectangle rect = new PDRectangle(50, 650, 200, 50);
        widget.setRectangle(rect);
        widget.setPage(page);
        page.getAnnotations().add(widget);
        acroForm.getFields().add(signatureField);
        document.save(args[0]);
    }
}
Also used : PDFont(org.apache.pdfbox.pdmodel.font.PDFont) PDPage(org.apache.pdfbox.pdmodel.PDPage) PDDocument(org.apache.pdfbox.pdmodel.PDDocument) PDResources(org.apache.pdfbox.pdmodel.PDResources) PDAnnotationWidget(org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationWidget) PDRectangle(org.apache.pdfbox.pdmodel.common.PDRectangle) PDAcroForm(org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm) PDSignatureField(org.apache.pdfbox.pdmodel.interactive.form.PDSignatureField)

Example 5 with PDSignatureField

use of org.apache.pdfbox.pdmodel.interactive.form.PDSignatureField in project pdfbox by apache.

the class CreateVisibleSignature2 method createVisualSignatureTemplate.

// create a template PDF document with empty signature and return it as a stream.
private InputStream createVisualSignatureTemplate(PDDocument srcDoc, int pageNum, PDRectangle rect) throws IOException {
    try (PDDocument doc = new PDDocument()) {
        PDPage page = new PDPage(srcDoc.getPage(pageNum).getMediaBox());
        doc.addPage(page);
        PDAcroForm acroForm = new PDAcroForm(doc);
        doc.getDocumentCatalog().setAcroForm(acroForm);
        PDSignatureField signatureField = new PDSignatureField(acroForm);
        PDAnnotationWidget widget = signatureField.getWidgets().get(0);
        List<PDField> acroFormFields = acroForm.getFields();
        acroForm.setSignaturesExist(true);
        acroForm.setAppendOnly(true);
        acroForm.getCOSObject().setDirect(true);
        acroFormFields.add(signatureField);
        widget.setRectangle(rect);
        // from PDVisualSigBuilder.createHolderForm()
        PDStream stream = new PDStream(doc);
        PDFormXObject form = new PDFormXObject(stream);
        PDResources res = new PDResources();
        form.setResources(res);
        form.setFormType(1);
        PDRectangle bbox = new PDRectangle(rect.getWidth(), rect.getHeight());
        float height = bbox.getHeight();
        Matrix initialScale = null;
        switch(srcDoc.getPage(pageNum).getRotation()) {
            case 90:
                form.setMatrix(AffineTransform.getQuadrantRotateInstance(1));
                initialScale = Matrix.getScaleInstance(bbox.getWidth() / bbox.getHeight(), bbox.getHeight() / bbox.getWidth());
                height = bbox.getWidth();
                break;
            case 180:
                form.setMatrix(AffineTransform.getQuadrantRotateInstance(2));
                break;
            case 270:
                form.setMatrix(AffineTransform.getQuadrantRotateInstance(3));
                initialScale = Matrix.getScaleInstance(bbox.getWidth() / bbox.getHeight(), bbox.getHeight() / bbox.getWidth());
                height = bbox.getWidth();
                break;
            case 0:
            default:
                break;
        }
        form.setBBox(bbox);
        PDFont font = PDType1Font.HELVETICA_BOLD;
        // from PDVisualSigBuilder.createAppearanceDictionary()
        PDAppearanceDictionary appearance = new PDAppearanceDictionary();
        appearance.getCOSObject().setDirect(true);
        PDAppearanceStream appearanceStream = new PDAppearanceStream(form.getCOSObject());
        appearance.setNormalAppearance(appearanceStream);
        widget.setAppearance(appearance);
        try (PDPageContentStream cs = new PDPageContentStream(doc, appearanceStream)) {
            // why does scale have no effect when done in the form matrix???
            if (initialScale != null) {
                cs.transform(initialScale);
            }
            // show background (just for debugging, to see the rect size + position)
            cs.setNonStrokingColor(Color.yellow);
            cs.addRect(-5000, -5000, 10000, 10000);
            cs.fill();
            // show background image
            // save and restore graphics if the image is too large and needs to be scaled
            cs.saveGraphicsState();
            cs.transform(Matrix.getScaleInstance(0.25f, 0.25f));
            PDImageXObject img = PDImageXObject.createFromFileByExtension(imageFile, doc);
            cs.drawImage(img, 0, 0);
            cs.restoreGraphicsState();
            // show text
            float fontSize = 10;
            float leading = fontSize * 1.5f;
            cs.beginText();
            cs.setFont(font, fontSize);
            cs.setNonStrokingColor(Color.black);
            cs.newLineAtOffset(fontSize, height - leading);
            cs.setLeading(leading);
            cs.showText("(Signature very wide line 1)");
            cs.newLine();
            cs.showText("(Signature very wide line 2)");
            cs.newLine();
            cs.showText("(Signature very wide line 3)");
            cs.endText();
        }
        // no need to set annotations and /P entry
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        doc.save(baos);
        return new ByteArrayInputStream(baos.toByteArray());
    }
}
Also used : PDFont(org.apache.pdfbox.pdmodel.font.PDFont) PDField(org.apache.pdfbox.pdmodel.interactive.form.PDField) PDPage(org.apache.pdfbox.pdmodel.PDPage) PDAppearanceStream(org.apache.pdfbox.pdmodel.interactive.annotation.PDAppearanceStream) PDResources(org.apache.pdfbox.pdmodel.PDResources) PDAcroForm(org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm) PDStream(org.apache.pdfbox.pdmodel.common.PDStream) ByteArrayOutputStream(java.io.ByteArrayOutputStream) PDImageXObject(org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject) Matrix(org.apache.pdfbox.util.Matrix) PDAppearanceDictionary(org.apache.pdfbox.pdmodel.interactive.annotation.PDAppearanceDictionary) ByteArrayInputStream(java.io.ByteArrayInputStream) PDDocument(org.apache.pdfbox.pdmodel.PDDocument) PDAnnotationWidget(org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationWidget) PDFormXObject(org.apache.pdfbox.pdmodel.graphics.form.PDFormXObject) PDRectangle(org.apache.pdfbox.pdmodel.common.PDRectangle) PDPageContentStream(org.apache.pdfbox.pdmodel.PDPageContentStream) PDSignatureField(org.apache.pdfbox.pdmodel.interactive.form.PDSignatureField)

Aggregations

PDSignatureField (org.apache.pdfbox.pdmodel.interactive.form.PDSignatureField)10 PDAcroForm (org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm)7 PDField (org.apache.pdfbox.pdmodel.interactive.form.PDField)4 PDDocument (org.apache.pdfbox.pdmodel.PDDocument)3 PDPage (org.apache.pdfbox.pdmodel.PDPage)3 PDResources (org.apache.pdfbox.pdmodel.PDResources)3 PDRectangle (org.apache.pdfbox.pdmodel.common.PDRectangle)3 PDAnnotationWidget (org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationWidget)3 ByteArrayInputStream (java.io.ByteArrayInputStream)2 COSArrayList (org.apache.pdfbox.pdmodel.common.COSArrayList)2 PDStream (org.apache.pdfbox.pdmodel.common.PDStream)2 PDFont (org.apache.pdfbox.pdmodel.font.PDFont)2 PDFormXObject (org.apache.pdfbox.pdmodel.graphics.form.PDFormXObject)2 PDSignature (org.apache.pdfbox.pdmodel.interactive.digitalsignature.PDSignature)2 Point (java.awt.Point)1 AffineTransform (java.awt.geom.AffineTransform)1 ByteArrayOutputStream (java.io.ByteArrayOutputStream)1 InputStream (java.io.InputStream)1 ArrayList (java.util.ArrayList)1 COSArray (org.apache.pdfbox.cos.COSArray)1