VisualSignature.vb
''
'' This code is part of Document Solutions for PDF demos.
'' Copyright (c) MESCIUS inc. All rights reserved.
''
Imports System.IO
Imports System.Drawing
Imports GrapeCity.Documents.Pdf
Imports GrapeCity.Documents.Pdf.AcroForms
Imports GrapeCity.Documents.Text
Imports GrapeCity.Documents.Drawing
Imports GCTEXT = GrapeCity.Documents.Text
Imports GCDRAW = GrapeCity.Documents.Drawing
Imports System.Security.Cryptography.X509Certificates

'' This sample demonstrates how to create and sign a PDF with a .pfx file,
'' using a SignatureField and a signature image.
'' The sample then loads the signed file back into another GcPdfDocument instance
'' and verifies the signature.
'' This sample is identical to SignDoc, but adds an image representing the signature.
Public Class VisualSignature
    Function CreatePDF(ByVal stream As Stream) As Integer
        Dim doc = New GcPdfDocument()
        Dim page = doc.NewPage()
        Dim tf = New TextFormat() With {.Font = StandardFonts.Times, .FontSize = 14}
        page.Graphics.DrawString("Hello, World!" + vbLf +
            "Signed by DsPdfWeb VisualSignature sample.",
            tf, New PointF(72, 72))

        '' Init a test certificate:
        Dim pfxPath = Path.Combine("Resources", "Misc", "DsPdfTest.pfx")
        Dim cert = New X509Certificate2(File.ReadAllBytes(pfxPath), "qq",
                X509KeyStorageFlags.MachineKeySet Or X509KeyStorageFlags.PersistKeySet Or X509KeyStorageFlags.Exportable)
        Dim sp = New SignatureProperties() With
        {
            .SignatureBuilder = New Pkcs7SignatureBuilder() With {
                .CertificateChain = New X509Certificate2() {cert}
            },
            .Location = "DsPdfWeb Demo Browser",
            .SignerName = "DsPdfWeb"
        }

        '' Add an image representing the signature:
        sp.SignatureAppearance.Image = GCDRAW.Image.FromFile(Path.Combine("Resources", "ImagesBis", "signature.png"))
        sp.SignatureAppearance.CaptionImageRelation = GrapeCity.Documents.Pdf.Annotations.CaptionImageRelation.ImageOnly

        '' Init a signature field to hold the signature:
        Dim sf = New SignatureField()
        sf.Widget.Rect = New RectangleF(72, 72 * 2, 72 * 4, 36)
        sf.Widget.Page = page
        sf.Widget.BackColor = Color.LightSeaGreen
        sf.Widget.DefaultAppearance.Font = StandardFonts.Helvetica
        sf.Widget.ButtonAppearance.Caption = $"Signer: {sp.SignerName}{vbCrLf}Location: {sp.Location}"
        '' Add the signature field to the document:
        doc.AcroForm.Fields.Add(sf)
        '' Connect the signature field and signature props:
        sp.SignatureField = sf

        '' Sign and save the document:
        '' NOTES:
        '' - Signing and saving is an atomic operation, the two cannot be separated.
        '' - The stream passed to the Sign() method must be readable.
        doc.Sign(sp, stream)

        '' Rewind the stream to read the document just created 
        '' into another GcPdfDocument and verify the signature:
        stream.Seek(0, SeekOrigin.Begin)
        Dim doc2 = New GcPdfDocument()
        doc2.Load(stream)
        Dim sf2 = CType(doc2.AcroForm.Fields(0), SignatureField)
        If Not sf2.Value.VerifySignatureValue() Then
            Throw New Exception("Failed to verify the signature")
        End If

        '' Done (the generated and signed docment has already been saved to 'stream').
        Return doc.Pages.Count
    End Function
End Class