Setting appearance of sign field

Hi Jindrich,

GemBox.Pdf updates signature’s appearance on several occasions:

  • when the signature field is added to the document,
  • when signature appearance font settings are changed,
  • when the signature field value is changed (when calling PdfSignatureField.Sign method) and,
  • when the signed document is being saved to a file if the signature’s date should be updated to the latest value (if PdfSignatureAppearance.DateFormat is not String.Empty).

So, PdfSignatureAppearance.DateFormat should be set to String.Empty and signature appearance should be customized after calling PdfSignatureField.Sign method.

Please try using this latest bugfix version:
https://www.gemboxsoftware.com/pdf/nightlybuilds/GBA15v1101.zip
Or this latest package:
Install-Package GemBox.Pdf -Version 15.0.1101-hotfix

And try running the following code snippet which is a customization of a visible signature example.

string logo = "logo.png";
using (var document = PdfDocument.Load("Reading.pdf"))
{
    // Add a visible signature field to the first page of the PDF document.
    var signatureField = document.Form.Fields.AddSignature(document.Pages[0], 300, 500, 250, 50);

    // Retrieve signature appearance settings to customize it.
    var signatureAppearance = signatureField.Appearance;

    // Do not update signature appearance to the date/time of when the document is being saved to a file.
    signatureAppearance.DateFormat = string.Empty;

    // Make default signature appearance empty.
    signatureAppearance.Name = string.Empty;

    // Get a digital ID from PKCS#12/PFX file.
    var digitalId = new PdfDigitalId("GemBoxRSA1024.pfx", "GemBoxPassword");

    // Create a PDF signer that will create the digital signature.
    var signer = new PdfSigner(digitalId);

    // Adobe Acrobat Reader currently doesn't download certificate chain
    // so we will also embed certificate of intermediate Certificate Authority in the signature.
    // (see https://community.adobe.com/t5/acrobat/signature-validation-using-aia-extension-not-enabled-by-default/td-p/10729647)
    signer.ValidationInfo = new PdfSignatureValidationInfo(new PdfCertificate[] { new PdfCertificate("GemBoxRSA.crt") }, null, null);

    // Initiate signing of a PDF file with the specified signer.
    signatureField.Sign(signer);

    // Add an image behind the existing content of the appropriate signature appearance layer as specified in https://web.archive.org/web/20201020094806/https://www.adobe.com/content/dam/acom/en/devnet/acrobat/pdfs/PPKAppearances.pdf.
    var sigFieldDict = signatureField.GetDictionary();
    var ap = (PdfDictionary)sigFieldDict[PdfName.Create("AP")];
    var normalAppearanceDict = ((PdfStream)((PdfIndirectObject)ap[PdfName.Create("N")]).Value).Dictionary;
    var resources = (PdfDictionary)normalAppearanceDict[PdfName.Create("Resources")];
    var xObjectResources = (PdfDictionary)resources[PdfName.Create("XObject")];
    var formDict = ((PdfStream)((PdfIndirectObject)xObjectResources[PdfName.Create("FRM")]).Value).Dictionary;
    resources = (PdfDictionary)formDict[PdfName.Create("Resources")];
    xObjectResources = (PdfDictionary)resources[PdfName.Create("XObject")];
    formDict = ((PdfStream)((PdfIndirectObject)xObjectResources[PdfName.Create("n2")]).Value).Dictionary;
    resources = (PdfDictionary)formDict[PdfName.Create("Resources")];
    resources.Add(PdfName.Create("XObject"), xObjectResources = PdfDictionary.Create());
    var image = PdfImage.Load(logo);
    var imageDict = image.GetDictionary();
    if (imageDict.Stream.Indirect == null)
        PdfIndirectObject.Create(imageDict.Stream);
    xObjectResources.Add(PdfName.Create("Im0"), imageDict.Stream.Indirect);
    PdfPoint point = new PdfPoint(0, 0);
    PdfSize size = image.Size;
    byte[] existingContent;
    using (var streamData = formDict.Stream.Open(PdfStreamDataMode.Read, PdfStreamDataState.Decoded))
    using (var memoryStream = new MemoryStream())
    {
        streamData.CopyTo(memoryStream);
        existingContent = memoryStream.ToArray();
    }
    byte[] newContent = Encoding.ASCII.GetBytes(string.Format(CultureInfo.InvariantCulture, "q {0} 0 0 {1} {2} {3} cm /Im0 Do Q", size.Width, size.Height, point.X, point.Y));
    using (var streamData = formDict.Stream.Open(PdfStreamDataMode.Write, PdfStreamDataState.Decoded))
    {
        streamData.Write(newContent, 0, newContent.Length);
        if (existingContent.Length > 0)
        {
            streamData.WriteByte((byte)'\n');
            streamData.Write(existingContent, 0, existingContent.Length);
        }
    }

    // Finish signing of a PDF file.
    document.Save("Visible Digital Signature.pdf");
}

I hope this helps.

Regards,
Mario