Search in sources :

Example 1 with PDAnnotation

use of com.tom_roush.pdfbox.pdmodel.interactive.annotation.PDAnnotation in project PdfBox-Android by TomRoush.

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.
 * <p>
 * Only one signature may be added in a document. To sign several times,
 * load document, add signature, save incremental and close again.
 *
 * @param sigObject is the PDSignatureField model
 * @param signatureInterface is an interface whose implementation provides
 * signing capabilities. Can be null if external signing if used.
 * @param options signature options
 * @throws IOException if there is an error creating required fields
 * @throws IllegalStateException if one attempts to add several signature
 * fields.
 */
public void addSignature(PDSignature sigObject, SignatureInterface signatureInterface, SignatureOptions options) throws IOException {
    if (signatureAdded) {
        throw new IllegalStateException("Only one signature may be added in a document");
    }
    signatureAdded = true;
    // 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(com.tom_roush.pdfbox.pdmodel.interactive.form.PDField) PDAnnotation(com.tom_roush.pdfbox.pdmodel.interactive.annotation.PDAnnotation) COSDocument(com.tom_roush.pdfbox.cos.COSDocument) PDAcroForm(com.tom_roush.pdfbox.pdmodel.interactive.form.PDAcroForm) COSArrayList(com.tom_roush.pdfbox.pdmodel.common.COSArrayList) COSArray(com.tom_roush.pdfbox.cos.COSArray) PDAnnotationWidget(com.tom_roush.pdfbox.pdmodel.interactive.annotation.PDAnnotationWidget) PDSignatureField(com.tom_roush.pdfbox.pdmodel.interactive.form.PDSignatureField)

Example 2 with PDAnnotation

use of com.tom_roush.pdfbox.pdmodel.interactive.annotation.PDAnnotation in project PdfBox-Android by TomRoush.

the class Splitter method processAnnotations.

private void processAnnotations(PDPage imported) throws IOException {
    List<PDAnnotation> annotations = imported.getAnnotations();
    for (PDAnnotation annotation : annotations) {
        if (annotation instanceof PDAnnotationLink) {
            PDAnnotationLink link = (PDAnnotationLink) annotation;
            PDDestination destination = link.getDestination();
            if (destination == null && link.getAction() != null) {
                PDAction action = link.getAction();
                if (action instanceof PDActionGoTo) {
                    destination = ((PDActionGoTo) action).getDestination();
                }
            }
            if (destination instanceof PDPageDestination) {
                // TODO preserve links to pages within the split result
                ((PDPageDestination) destination).setPage(null);
            }
        }
        // TODO preserve links to pages within the split result
        annotation.setPage(null);
    }
}
Also used : PDAction(com.tom_roush.pdfbox.pdmodel.interactive.action.PDAction) PDAnnotation(com.tom_roush.pdfbox.pdmodel.interactive.annotation.PDAnnotation) PDPageDestination(com.tom_roush.pdfbox.pdmodel.interactive.documentnavigation.destination.PDPageDestination) PDDestination(com.tom_roush.pdfbox.pdmodel.interactive.documentnavigation.destination.PDDestination) PDAnnotationLink(com.tom_roush.pdfbox.pdmodel.interactive.annotation.PDAnnotationLink) PDActionGoTo(com.tom_roush.pdfbox.pdmodel.interactive.action.PDActionGoTo)

Example 3 with PDAnnotation

use of com.tom_roush.pdfbox.pdmodel.interactive.annotation.PDAnnotation in project PdfBox-Android by TomRoush.

the class TestPDPageAnnotationsFiltering method validateAllFiltered.

@Test
public void validateAllFiltered() throws IOException {
    List<PDAnnotation> annotations = page.getAnnotations(new AnnotationFilter() {

        @Override
        public boolean accept(PDAnnotation annotation) {
            return false;
        }
    });
    Assert.assertEquals(0, annotations.size());
}
Also used : PDAnnotation(com.tom_roush.pdfbox.pdmodel.interactive.annotation.PDAnnotation) AnnotationFilter(com.tom_roush.pdfbox.pdmodel.interactive.annotation.AnnotationFilter) Test(org.junit.Test)

Example 4 with PDAnnotation

use of com.tom_roush.pdfbox.pdmodel.interactive.annotation.PDAnnotation in project PdfBox-Android by TomRoush.

the class COSArrayListTest method setUp.

/*
    * Create thre new different annotations an add them to the Java List/Array as
    * well as PDFBox List/Array implementations.
    */
@Before
public void setUp() throws Exception {
    annotationsList = new ArrayList<PDAnnotation>();
    PDAnnotationTextMarkup txtMark = new PDAnnotationTextMarkup(PDAnnotationTextMarkup.SUB_TYPE_HIGHLIGHT);
    PDAnnotationLink txtLink = new PDAnnotationLink();
    PDAnnotationSquareCircle aCircle = new PDAnnotationSquareCircle(PDAnnotationSquareCircle.SUB_TYPE_CIRCLE);
    annotationsList.add(txtMark);
    annotationsList.add(txtLink);
    annotationsList.add(aCircle);
    assertTrue(annotationsList.size() == 3);
    tbcAnnotationsList = new ArrayList<PDAnnotation>();
    tbcAnnotationsList.add(txtMark);
    tbcAnnotationsList.add(txtLink);
    tbcAnnotationsList.add(aCircle);
    assertTrue(tbcAnnotationsList.size() == 3);
    annotationsArray = new COSArray();
    annotationsArray.add(txtMark);
    annotationsArray.add(txtLink);
    annotationsArray.add(aCircle);
    assertTrue(annotationsArray.size() == 3);
    tbcAnnotationsArray = new COSBase[3];
    tbcAnnotationsArray[0] = txtMark.getCOSObject();
    tbcAnnotationsArray[1] = txtLink.getCOSObject();
    tbcAnnotationsArray[2] = aCircle.getCOSObject();
    assertTrue(tbcAnnotationsArray.length == 3);
    // add the annotations to the page
    pdPage = new PDPage();
    pdPage.setAnnotations(annotationsList);
}
Also used : COSArray(com.tom_roush.pdfbox.cos.COSArray) PDPage(com.tom_roush.pdfbox.pdmodel.PDPage) PDAnnotationTextMarkup(com.tom_roush.pdfbox.pdmodel.interactive.annotation.PDAnnotationTextMarkup) PDAnnotation(com.tom_roush.pdfbox.pdmodel.interactive.annotation.PDAnnotation) PDAnnotationLink(com.tom_roush.pdfbox.pdmodel.interactive.annotation.PDAnnotationLink) PDAnnotationSquareCircle(com.tom_roush.pdfbox.pdmodel.interactive.annotation.PDAnnotationSquareCircle) Before(org.junit.Before)

Example 5 with PDAnnotation

use of com.tom_roush.pdfbox.pdmodel.interactive.annotation.PDAnnotation in project PdfBox-Android by TomRoush.

the class COSArrayListTest method removeFromListByObject.

/**
 * Test removing a PDModel element by index is in sync with underlying COSArray
 */
@Test
public void removeFromListByObject() throws Exception {
    COSArrayList<PDAnnotation> cosArrayList = new COSArrayList<PDAnnotation>(annotationsList, annotationsArray);
    int positionToRemove = 1;
    PDAnnotation toBeRemoved = tbcAnnotationsList.get(positionToRemove);
    cosArrayList.remove(toBeRemoved);
    assertTrue("List size shall be 2", cosArrayList.size() == 2);
    assertTrue("COSArray size shall be 2", annotationsArray.size() == 2);
    PDAnnotation annot = (PDAnnotation) cosArrayList.get(1);
    assertTrue("Object at original position 2 shall now be at position 1 in underlying COSArray", annotationsArray.indexOf(annot.getCOSObject()) == 1);
    // compare with Java List/Array to ensure correct object at position
    assertTrue("List object at 2 is at position 1 in COSArrayList now", cosArrayList.indexOf(tbcAnnotationsList.get(2)) == 1);
    assertTrue("COSObject of List object at 2 is at position 1 in COSArray now", annotationsArray.indexOf(tbcAnnotationsList.get(2).getCOSObject()) == 1);
    assertTrue("Array object at 2 is at position 1 in underlying COSArray now", annotationsArray.indexOf(tbcAnnotationsArray[2]) == 1);
    assertTrue("PDAnnotation shall no longer exist in List", cosArrayList.indexOf(tbcAnnotationsList.get(positionToRemove)) == -1);
    assertTrue("COSObject shall no longer exist in COSArray", annotationsArray.indexOf(tbcAnnotationsArray[positionToRemove]) == -1);
}
Also used : PDAnnotation(com.tom_roush.pdfbox.pdmodel.interactive.annotation.PDAnnotation) Test(org.junit.Test)

Aggregations

PDAnnotation (com.tom_roush.pdfbox.pdmodel.interactive.annotation.PDAnnotation)21 Test (org.junit.Test)9 COSArray (com.tom_roush.pdfbox.cos.COSArray)6 PDPage (com.tom_roush.pdfbox.pdmodel.PDPage)5 PDAnnotationLink (com.tom_roush.pdfbox.pdmodel.interactive.annotation.PDAnnotationLink)5 COSDictionary (com.tom_roush.pdfbox.cos.COSDictionary)4 AnnotationFilter (com.tom_roush.pdfbox.pdmodel.interactive.annotation.AnnotationFilter)4 COSBase (com.tom_roush.pdfbox.cos.COSBase)3 COSArrayList (com.tom_roush.pdfbox.pdmodel.common.COSArrayList)3 PDAnnotationSquareCircle (com.tom_roush.pdfbox.pdmodel.interactive.annotation.PDAnnotationSquareCircle)3 PDAnnotationWidget (com.tom_roush.pdfbox.pdmodel.interactive.annotation.PDAnnotationWidget)3 ArrayList (java.util.ArrayList)3 COSName (com.tom_roush.pdfbox.cos.COSName)2 COSStream (com.tom_roush.pdfbox.cos.COSStream)2 PDDocumentCatalog (com.tom_roush.pdfbox.pdmodel.PDDocumentCatalog)2 PDDocumentNameDestinationDictionary (com.tom_roush.pdfbox.pdmodel.PDDocumentNameDestinationDictionary)2 COSObjectable (com.tom_roush.pdfbox.pdmodel.common.COSObjectable)2 PDNumberTreeNode (com.tom_roush.pdfbox.pdmodel.common.PDNumberTreeNode)2 PDActionGoTo (com.tom_roush.pdfbox.pdmodel.interactive.action.PDActionGoTo)2 PDDestination (com.tom_roush.pdfbox.pdmodel.interactive.documentnavigation.destination.PDDestination)2