GroupDocs.Signature for Java 21.5 Release Notes

Major Features

This release contains important improvements for PDF Digital signatures, for signature image preview generation, changes with the additional signature options properties and bug fixes. Below the list of most notable changes in release of GroupDocs.Signature for Java 21.5:

  • Introduced extended customization of PDF Digital signatures appearance.
  • Implemented ability to apply signature extensions to Digital Signatures.
  • Fixed bug with restoring signatures metadata from signed image documents.
  • Implemented additional customization of Pdf Digital Signature appearance.
  • Improved saving Open Office documents with the OTT file format.
  • Implemented support of Native Text Signature implementation on the Image documents.
  • Fixed major issues with reading and signing Word processing documents.
  • Fixed issues with the image rendering for the Spreadsheet documents.
  • Fixed null-references bugs with accessing not initialized objects across the signing process.
  • The issue on Document preview generation with not hidden signatures was fixed.
  • Unexpected identifiers in the result for digitally signed PDF Documents were fixed.
  • Fixed the wrong signature identifiers in the signing result for all supported file formats.
  • Implemented ability to retrieve Signatures preview for the given Signature Options.
  • Involved signature deletion by the certain Signature type (Text, Image, Barcode, QRCode, Digital).
  • Improved electronic certificates removal from the WordProcesing, Spreadsheet and Presentation documents.
  • Fixed page generation preview issues with the Qr-Code signatures.
  • Fixed issues with the image rendering for the Spreadsheet documents.
  • Implemented ability to support Border properties for PDF Digital signature on document page.
  • Improved generation of digital signature image preview for Pdf document.
  • Implemented additional properties Siganture Type and Document Type that allow to distinct the options and specify document type for signature preview.
  • Fixed the issue with Word Processing document Watermark objects.

Full List of Issues Covering all Changes in this Release

KeySummaryIssue Type
SIGNATURENET-3136Improve PDF Digital Appearance implementation to support all image related extensionsFeature
SIGNATURENET-3104Implement CustomAppearance property for PDF Digital SignatureFeature
SIGNATURENET-3127Improve processing nullable Font properties entire options with default valuesImprovement
SIGNATURENET-3136-3133Exception Specified cast is not valid when processing signed image documentsBug
SIGNATURENET-3131Incorrect Page count when obtaining .Odt documents format informationBug
SIGNATURENET-3130Null reference exception occurs for applying Text signature options with nullable Font propertyBug
SIGNATURENET-3128This file type is not supportedBug
SIGNATURENET-2971Word-processing blank document preview doesn’t contain trial messageBug
SIGNATURENET-3207Implement Font customization for Pdf Digital Signature AppearanceFeature
SIGNATURENET-3188Open office document content is slightly changed after saving for OTT format typesImprovement
SIGNATURENET-3139Involve support of Text Signature options with Native implementation for Image documentsImprovement
SIGNATURENET-3187Exception while obtaining watermark type for Word processing documentsBug
SIGNATURENET-3186Can not sign second page of Word processing documentBug
SIGNATURENET-3185Document Information returns incorrect number of pages for Pdf filesBug
SIGNATURENET-3184Can not sign Open Office document for ODT format filesBug
SIGNATURENET-3183A generic error occurred in GDI+ for Spreadsheet documentsBug
SIGNATURENET-3160NullReference exception occurs when Text property of StampLine is not set for Stamp SignaturesBug
SIGNATURENET-3158NullReference exception occurs when Margin property of signature options is nullBug
SIGNATURENET-3280Preview with hidden signatures contains QrCode signature image for Word processing documentsBug
SIGNATURENET-3277Result of digitally signed documents contains wrong Digital signature identifiersBug
SIGNATURENET-3234Signed result of Pdf document returns unexpected Signature identifierBug
SIGNATURENET-3358Implement ability to retrieve Stamp Signature Image Preview without documentFeature
SIGNATURENET-3357Implement ability to retrieve Digital Signature Image Preview without documentFeature
SIGNATURENET-3356Implement ability to retrieve Text Signature image preview without documentFeature
SIGNATURENET-3331Implement the ability to remove signatures of the certain typeFeature
SIGNATURENET-3329Implement ability to retrieve QR-code signature image without documentFeature
SIGNATURENET-3328Implement ability to retrieve Barcode signature image without documentFeature
SIGNATURENET-3282Implement ability to remove digital signatures from Spreadsheet documentsFeature
SIGNATURENET-3281Implement ability to remove all digital signatures from Presentation documentsFeature
SIGNATURENET-3233Implement ability to remove digital signatures from Word Processing documentsFeature
SIGNATURENET-3283Preview with hidden signatures contains QrCode signatureBug
SIGNATURENET-3258Error “startIndex cannot be larger than length of string. Parameter name: startIndex” for Spreadsheet documentsBug
SIGNATURENET-3410Implement support of Border properties for the Pdf Digital AppearanceImprovement
SIGNATURENET-3389Implement special generation of the Digital Signature image preview for PDF Document typeImprovement
SIGNATURENET-3388Implement public enum Document Type to distinct document optionsImprovement
SIGNATURENET-3363Implement SignOptions.SignatureType propertyImprovement
SIGNATURENET-3309Unexpected Words Processing document behavior with watermark objectsBug

Public Developer Guide examples changes

Following topics from Developer Guide were added

Delete Digital signatures from documents

Delete Signatures of the certain type

Generate Signatures preview

Advanced Signatures removal of the certain types

Public API and Backward Incompatible Changes

New class PdfDigitalSignatureAppearance was added with several properties that allow to customize appearance of digital sigantures on the PDF Document pages.

New class PdfDigitalSignatureAppearance contains follow properties.

New class PdfDigitalSignatureAppearance

public final class PdfDigitalSignatureAppearance extends SignatureAppearance
{
    /**
     * <p>
     * Gets or sets contact info label. Default value: "Contact".
     * if this value is empty then no contact label will appear on digital signature area.
     * </p>
     */    
    public final String getContactInfoLabel();
    public final void setContactInfoLabel(String value);

    /**
     * <p>
     * Gets or sets reason label. Default value: "Reason".
     * if this value is empty then no reason label will appear on digital signature area.
     * </p>
     */    
    public final String getReasonLabel();
    public final void setReasonLabel(String value);

    /**
     * <p>
     * Gets or sets location label. Default value: "Location".
     * if this value is empty then no location label will appear on digital signature area.
     * </p>
     */    
    public final String getLocationLabel();
    public final void setLocationLabel(String value);

    /**
     * <p>
     * Gets or sets digital signed label. Default value: "Digitally signed by".
     * </p>
     */    
    public final String getDigitalSignedLabel();
    public final void setDigitalSignedLabel(String value);

    /**
     * <p>
     * Gets or sets date signed label. Default value: "Date".
     * </p>
     */    
    public final String getDateSignedAtLabel();
    public final void setDateSignedAtLabel(String value);
	
	/**
	 * <p>
	 * Get or set background color of signature appearance.
	 * By default the value is SystemColors.Windows
	 * </p>
	 */    
    public final java.awt.Color getBackground();
    public final void setBackground(java.awt.Color value);

    /**
     * <p>
     * Gets or sets the Font family name to display the labels. Default value is "Arial".
     * </p>
     */   
    public final String getFontFamilyName();    
    public final void setFontFamilyName(String value);

    /**
     * <p>
     * Gets or sets the Font size to display the labels. Default value is 10.
     * </p>
     */    
    public final double getFontSize();    
    public final void setFontSize(double value);
    

    /**
     * <p>
     * Creates signature appearance object with default values.
     * </p>
     */    
    public PdfDigitalSignatureAppearance();    
}

Following example shows how to sign PDF Document with customization of Digital signature appearance on the page.

// initialize Signature instance
Signature signature = new Signature("signed.pdf");

//Create digital signing options
DigitalSignOptions options = new DigitalSignOptions(certificatePath);
// certificate password
options.setPassword("1234567890");
// digital certificate details
options.setReason("Approved");
options.setLocation("New York");

// apply custom PDF signature appearance
PdfDigitalSignatureAppearance appearance = new PdfDigitalSignatureAppearance();

// do now show contact details
appearance.setContactInfoLabel("");
// simplify reason label
appearance.setReasonLabel("R:");
// change location label
appearance.setLocationLabel("@=>");
appearance.setDigitalSignedLabel("By:");
appearance.setDateSignedAtLabel("On");
// apply custom appearance color
appearance.setBackground(Color.red);
// apply custom font settings
appearance.setFontFamilyName("Courier");
appearance.setFontSize(8);

options.setAppearance(appearance);
//
options.setAllPages(true);
options.setWidth(160);
options.setHeight(80);
options.setVerticalAlignment(VerticalAlignment.Center);
options.setHorizontalAlignment(HorizontalAlignment.Left);
options.setMargin(new Padding(0, 10,0, 10));

// setup signature border
Border border = new Border();
border.setVisible(true);
border.setColor(Color.red);
border.setDashStyle(DashStyle.DashDot);
border.setWeight(2);
options.setBorder(border);

SignResult signResult = signature.sign("signed_out.pdf", options);
       

Public class Signature was updated with 2 new overload Delete methods

Method delete expects enumeration SignatureType.

Alternative overload method deleteByTypes expects list of the SignatureType enumeration.

New overload Delete methods of Signature class

    public class Signature
    {
       /**
		 * <p>
		 * Deletes signatures of the certain type {@link SignatureType} from the document.
		 * Only signatures that were added by Sign method and marked as Signatures {@code BaseSignature.isSignature()}({@link BaseSignature#isSignature}/{@link BaseSignature#setSignature(boolean)})  will be removed.
		 * Following signature types are supported: Text, Image, Digital, Barcode, QR-Code
		 * </p>
		 */
        public final DeleteResult delete(OutputStream document, int signatureType) throws Exception {};
        public final DeleteResult deleteByTypes(OutputStream document, java.util.List<Integer> signatureTypes) throws Exception {};
		public final DeleteResult delete(String filePath, int signatureType) throws Exception {};
		public final DeleteResult deleteByTypes(String filePath, java.util.List<Integer> signatureTypes) throws Exception{};
   }

Following example demonstrates how to remove all digital signatures from the document.

Deleting all Digital signatures from the document


	Signature signature = new Signature("signed.pdfx");
	{
		// deleting QR-Code signatures from the document
		DeleteResult result = signature.delete("signed_out.pdfx", SignatureType.Digital);
		if (result.getSucceeded().size() > 0)
		{
			System.out.print("Following Digital signatures were deleted:");
			int number = 1;
			for (BaseSignature temp : result.getSucceeded())
			{
				System.out.print("Signature #"+number++ +": Type: "+temp.getSignatureType()+" Id:"+temp.getSignatureId()+", Text: "+((DigitalSignature)temp).getText());
			}
		}
		else
		{
			System.out.print("No one Digital signature was deleted.");
		}
	}

New public class PreviewSignatureOptions was added to collect settings for signature preview

This class contains following properties

  • unique signature identifier SignatureId.
  • instance of the SignOptions.
  • enumeration of the preview image format

New static method GenerateSignaturePreview of Signature class

/**
 * <p>
 * Represents signature preview options.
 * </p>
 */
public class PreviewSignatureOptions
{
    /**
     * <p>
     * Unique value to distinct the signature.
     * Use SignatureId to identify the preview options.
     * </p>
     */    
    public final String getSignatureId(){};
    public final void setSignatureId(String value){};

    /**
     * <p>
     * Signature Options for generate preview.
     * </p>
     */    
    public final SignOptions getSignOptions(){};
    public final void setSignOptions(SignOptions value){};
    

    /**
     * <p>
     * Gets or sets preview images format.
     * Default value is PNG
     * </p>
     */    
    public final int getPreviewFormat(){};
    public final void setPreviewFormat(int value){};


    /**
     * <p>
     * Initializes PreviewSignatureOptions object.
     * </p>
     * @param signOptions The signature options to generate preview for.
     * @param pageStreamFactory Interface which defines method to create output page preview stream.
     */    
    public PreviewSignatureOptions(SignOptions signOptions, PageSignatureStreamFactory pageStreamFactory){};

}

/**
 * <p>
 * Document preview supported formats
 * </p>
 */
public class PreviewFormats extends Object
{
    private PreviewFormats(){}
    /**
     * <p>
     * PNG
     * </p>
     */
    public static final int PNG = 0;
    /**
     * <p>
     * JPEG
     * </p>
     */
    public static final int JPEG = 1;
    /**
     * <p>
     * BMP
     * </p>
     */
    public static final int BMP = 2;
}

Public class Signature was updated with static method to generate Signature preview with specified SignOptions

Static method generateSignaturePreview expects PreviewSignatureOptions to generate signature preview and control creation and deletion signature image stream.

New static method GenerateSignaturePreview of Signature class

   /**
	 * <p>
	 * Generates Signature preview based on given SignOptions. 
	 * </p>
	 */
   public static void generateSignaturePreview(PreviewSignatureOptions previewOptions) throws Exception{};
   

Following example demonstrates how to generate signature.

Generate signature preview


	public static void run() throws Exception
    {
		DigitalSignOptions signOptions = new DigitalSignOptions(MrSmithSignature.pfx);
        {
            // set the DocumentType property to specify simulating PDF signature appearance
            signOptions.setDocumentType(DocumentType.Pdf);
            // certificate password
            signOptions.setPassword("1234567890");
            // digital certificate details
            signOptions.setReason("Approved");
            signOptions.setContact("John Smith");
            signOptions.setLocation("New York");

            // apply custom PDF signature appearance
            PdfDigitalSignatureAppearance pdfDigSignAppearance = new PdfDigitalSignatureAppearance();
            {
                // do now show contact details
                pdfDigSignAppearance.setContactInfoLabel("Contact");
                // simplify reason label
                pdfDigSignAppearance.setReasonLabel("R:");
                // change location label
                pdfDigSignAppearance.setLocationLabel("@=>");
                pdfDigSignAppearance.setDigitalSignedLabel("By:");
                pdfDigSignAppearance.setDateSignedAtLabel("On:");
                // apply custom appearance color
                pdfDigSignAppearance.setBackground(Color.GRAY);
                // apply custom font settings
                pdfDigSignAppearance.setFontFamilyName("Courier");
                pdfDigSignAppearance.setFontSize(8);
            }
            //
            signOptions.setAllPages(false);
            signOptions.setWidth(200);
            signOptions.setHeight(130);
            signOptions.setVerticalAlignment(VerticalAlignment.Center);
            signOptions.setHorizontalAlignment(HorizontalAlignment.Left);
            Padding padding = new Padding();
            padding.setBottom(10);
            padding.setRight(10);
            signOptions.setMargin(padding);

            // setup signature border
            Border border = new Border();
            border.setVisible(true);
            border.setColor(Color.DARK_GRAY);
            border.setDashStyle(DashStyle.DashDot);
            border.setWeight(2);
            signOptions.setBorder(border);

        };

        // create signature preview options object
        PreviewSignatureOptions previewOption = new PreviewSignatureOptions(signOptions, new PageSignatureStreamFactory() {
            @Override
            public OutputStream createSignatureStream(PreviewSignatureOptions previewOptions) {
                return generateSignatureStream(previewOptions);
            }

            @Override
            public void closeSignatureStream(PreviewSignatureOptions previewOptions, OutputStream pageStream) {
                releaseSignatureStream(previewOptions, pageStream);
            }
        });

        previewOption.setSignatureId(UUID.randomUUID().toString());
        previewOption.setPreviewFormat(PreviewFormats.JPEG);

        // generate preview
        Signature.generateSignaturePreview(previewOption);
    }

    private static OutputStream generateSignatureStream(PreviewSignatureOptions previewOptions)
    {
        try {
            Path path = Paths.get(Constants.OutputPath, "\\GenerateSignaturePreviewAdvanced\\");
            if (!Files.exists(path)) {

                Files.createDirectory(path);
                System.out.println("Directory created");
            } else {

                System.out.println("Directory already exists");
            }
            File imageFilePath = new File(path+"\\signature"+previewOptions.getSignatureId()+"-"+previewOptions.getSignOptions().getSignatureType()+".jpg");
            return new FileOutputStream(imageFilePath);
        }catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        }

    }

    private static void releaseSignatureStream(PreviewSignatureOptions previewOptions, OutputStream signatureStream)
    {
        try {
            signatureStream.close();
            String imageFilePath = new File(Constants.OutputPath + "\\GeneratePreviewHideSignatures\\signature"+previewOptions.getSignatureId()+"-"+previewOptions.getSignOptions().getSignatureType()+".jpg").getPath();
            System.out.print("Image file "+imageFilePath+" is ready for preview");
        }catch (Exception e){
            throw new RuntimeException(e.getMessage());
        }
    }

New public enumeration DocumentType was added to distinct supported document types

This enumeration keeps supported Document types.

New public enumeration

    public final class DocumentType extends Object
{
    private DocumentType(){}
    /**
     * <p>Indicates an error, unknown document type.</p>
     */
    public static final int Unknown = 0;
    /**
     * <p>PDF Document Type.</p>
     */
    public static final int Pdf = 1;
    /**
     * <p>Word Processing Document Type.</p>
     */
    public static final int WordProcessing = 2;
    /**
     * <p>Presentation Document Type.</p>
     */
    public static final int Presentation = 3;
    /**
     * <p>Spreadsheet Document Type.</p>
     */
    public static final int Spreadsheet = 4;
    /**
     * <p>Image Document Type.</p>
     */
    public static final int Image = 5;
	
}

Public class SignOptions was updated with 2 new properties that allow to distinct signature type and document type

Public class SignOptions was updated with properties

New properties of SignOptions class

    public abstract class SignOptions
{
    /**
     * <p>
     * Get Signature Type
     * </p>
     */      
    public final int getSignatureType(){};

	 /**
     * <p>
     * Document Type (Spreadsheets, Presentations, Pdf, Words, Image)
     * </p>
     */    
    public final int getDocumentType(){};
    public final void setDocumentType(int value){};
   }