Warm tip: This article is reproduced from stackoverflow.com, please click
.net c# itext7 pdf

Add signature field on rotated document

发布于 2020-05-08 18:40:55

I am trying to add signature field on rotated document but I want to have no rotation applied on signature field and it should be added on rotated page with 0 rotation.

I have tried the following method but it does not work for me.

page.SetIgnorePageRotationForContent(true);

Could anyone provide solution of this issue?

screen shots

Signature appearance code snippet:

    PdfFormXObject layer2Object = _pdfSignatureAppearance.GetLayer2();

    PdfCanvas pdfCanvas = new PdfCanvas(layer2Object, _pdfSigner.GetDocument());
    PdfPage page = _pdfSigner.GetDocument().GetPage(signingRequest.Page <= 0 ? 
    signingRequest.PageNumber : signingRequest.Page);
    page = page.SetIgnorePageRotationForContent(false);
    int pageRotation = page.GetRotation();
    Canvas appearanceCanvas = new Canvas(pdfCanvas, _pdfSigner.GetDocument(), 
    layer2Object.GetBBox().ToRectangle());

    ImageData signatureImageData = 
    ImageDataFactory.Create(signingRequest.SignatureImage);
    Image signatureImage = new Image(signatureImageData);
    signatureImageData.SetRotation(0f);
    ImageData logoImageData = 
    ImageDataFactory.Create(Convert.FromBase64String(signingRequest.Logo));
    Image logoImage = new Image(logoImageData);
 logoImageData.SetRotation(0f);

KeyValuePair<string, SignatureAppearanceField> handSignatureKey = appearanceFieldSettings.Where(o => o.Key == SignatureAppearanceAttributes.HAND_SIGNATURE.ToString()).FirstOrDefault();
 appearanceAttributes = new Paragraph().SetWidth(UnitValue.CreatePercentValue(100)).SetHeight(UnitValue.CreatePercentValue(100)).SetMargin(0.01f).SetStrokeWidth(0.1f);
 handSignatureImage.SetHorizontalAlignment(iText.Layout.Properties.HorizontalAlignment.LEFT);
 handSignatureImage = handSignatureImage.SetAutoScale(true);
 handSignatureImage.SetMarginLeft((handSignatureKey.Value.X / aspectRatio) + 10);
 if (appearanceFieldSettings.ContainsKey("COMPANY_LOGO"))
 {
 if (fieldSettings.Key == SignatureAppearanceAttributes.COMPANY_LOGO.ToString())
 {
 IList<Image> images = new List<Image>();
 KeyValuePair<string, SignatureAppearanceField> companySignatureKey = appearanceFieldSettings.Where(o => o.Key == SignatureAppearanceAttributes.COMPANY_LOGO.ToString()).FirstOrDefault();
 companyLogoImage.SetAutoScale(true);
 companyLogoImage.SetHorizontalAlignment(iText.Layout.Properties.HorizontalAlignment.RIGHT);
 companyLogoImage.SetMarginLeft((companySignatureKey.Value.Width / aspectRatio) - 20);
 images.Add(handSignatureImage);
 images.Add(companyLogoImage);
 appearanceAttributes.AddAll(images);
if (pageRotation > 0)
 {
 handSignatureImage.SetRotationAngle((Math.PI / 180) * pageRotation);
 companyLogoImage.SetRotationAngle((Math.PI / 180) * pageRotation);
 appearanceAttributes.SetRotationAngle((Math.PI / 180) * pageRotation);
 }
appearanceCanvas.Add(appearanceAttributes);
 }
 }
 else
 {
 if (pageRotation > 0)
 {
 handSignatureImage.SetRotationAngle((Math.PI / 180) * pageRotation);
 appearanceAttributes.SetRotationAngle((Math.PI / 180) * pageRotation);
 }
 appearanceAttributes.Add(handSignatureImage);
 appearanceCanvas.Add(appearanceAttributes);
 }

Setting signed by and signing reason;

    KeyValuePair<string, SignatureAppearanceField> signingReasonKey = appearanceFieldSettings.Where(o => o.Key == SignatureAppearanceAttributes.SIGNING_REASON.ToString()).FirstOrDefault();
 string reason = !string.IsNullOrEmpty(signingRequest.WitnessReason) ? signingRequest.WitnessReason : signingRequest.SigningReason;
 if (reason.Length > 25)
 reason = reason.Substring(0, 25) + " ...";
 Text signingReasonText = null;
 appearanceAttributes = new Paragraph().SetFontSize(signingReasonKey.Value.Font.FontSize / aspectRatio).SetMargin(0.01f).SetStrokeWidth(0.1f);
 if (signingReasonKey.Value.ShowLabel)
 {
 signingReasonText = new Text(signingReasonKey.Value.LabelName + ": " + reason);
 }
 else
 {
 signingReasonText = new Text(reason);
 }
if (pageRotation > 0)
 {
 appearanceAttributes.SetRotationAngle((Math.PI / 180) * pageRotation);
 }
appearanceAttributes.Add(signingReasonText);
 appearanceCanvas.Add(appearanceAttributes);

enter image description here

Questioner
Muddassir Awan
Viewed
35
mkl 2020-03-09 20:33

I used the revision from your example file which has two empty signature fields and which is not yet signed. Furthermore, I used a re-built version of your signature image.

Using iText default appearances

As a first check I applied regular iText signing code in which iText itself fills the appearance of the signature:

using (PdfReader pdfReader = new PdfReader(PDF_SOURCE))
{
    PdfSigner pdfSigner = new PdfSigner(pdfReader, File.Create(PDF_DEST), new StampingProperties().UseAppendMode());
    ImageData imageData = ImageDataFactory.Create(IMAGE_SOURCE);

    pdfSigner.SetFieldName("SH_SIGNATURE_417868");

    PdfSignatureAppearance sigAppearance = pdfSigner.GetSignatureAppearance();
    sigAppearance.SetContact("ContactInfo");
    sigAppearance.SetLocation("Location");
    sigAppearance.SetReason("SigningReason");
    sigAppearance.SetLayer2Text("Muddassir Awan");
    sigAppearance.SetSignatureGraphic(imageData);
    sigAppearance.SetRenderingMode(RenderingMode.GRAPHIC_AND_DESCRIPTION);
    sigAppearance.SetSignatureCreator("Muddassir Awan");

    int estimatedSize = 12000;
    pdfSigner.SignExternalContainer(new ExternalBlankSignatureContainer(PdfName.Adobe_PPKLite, PdfName.Adbe_pkcs7_detached), estimatedSize);
}

The result:

Screen shot

Thus, this works.

Apparently, though, you want the data to be arranged differently, so we have to try to essentially do the same as the appearance generation code of iText merely with a different arrangement of the components.

Using custom appearances

As the iText code works (as seen above) and your code references a number of variables I don't have here, I wrote this from scratch, borrowing code from iText (PdfSignatureAppearance.GetAppearance() to be more precise), aiming at creating an appearance somewhat similar to your screenshot for a non-rotated document:

using (PdfReader pdfReader = new PdfReader(PDF_SOURCE))
{
    PdfSigner pdfSigner = new PdfSigner(pdfReader, File.Create(PDF_DEST), new StampingProperties().UseAppendMode());

    ImageData signatureImageData = ImageDataFactory.Create(IMAGE_SOURCE);
    Image signatureImage = new Image(signatureImageData);

    pdfSigner.SetFieldName("SH_SIGNATURE_417868");

    PdfSignatureAppearance sigAppearance = pdfSigner.GetSignatureAppearance();
    sigAppearance.SetContact("ContactInfo");
    sigAppearance.SetLocation("Location");
    sigAppearance.SetReason("SigningReason");
    sigAppearance.SetSignatureCreator("Muddassir Awan");

    PdfPage page = pdfSigner.GetDocument().GetPage(sigAppearance.GetPageNumber());
    int rotation = page.GetRotation();

    PdfFormXObject layer2Object = sigAppearance.GetLayer2();
    Rectangle rect = layer2Object.GetBBox().ToRectangle();
    PdfCanvas pdfCanvas = new PdfCanvas(layer2Object, pdfSigner.GetDocument());

    if (rotation == 90)
        pdfCanvas.ConcatMatrix(0, 1, -1, 0, rect.GetWidth(), 0);
    else if (rotation == 180)
        pdfCanvas.ConcatMatrix(-1, 0, 0, -1, rect.GetWidth(), rect.GetHeight());
    else if (rotation == 270)
        pdfCanvas.ConcatMatrix(0, -1, 1, 0, 0, rect.GetHeight());

    Rectangle rotatedRect = 0 == (rotation / 90) % 2 ? new Rectangle(rect.GetWidth(), rect.GetHeight()) : new Rectangle(rect.GetHeight(), rect.GetWidth());
    Canvas appearanceCanvas = new Canvas(pdfCanvas, pdfSigner.GetDocument(), rotatedRect);

    Paragraph text = new Paragraph();
    text.SetFontSize(7).Add("Signed by: Muddassir Awan\nReason: I approve this document\nSigned at: 2020-02-20 16:55:20 +05:00");
    appearanceCanvas.Add(text);

    signatureImage.ScaleToFit(rotatedRect.GetWidth(), 40);
    appearanceCanvas.Add(signatureImage);

    int estimatedSize = 12000;
    pdfSigner.SignExternalContainer(new ExternalBlankSignatureContainer(PdfName.Adobe_PPKLite, PdfName.Adbe_pkcs7_detached), estimatedSize);
}

The result:

screen shot

This is approximately what you want, except for the position fine tuning.

So one merely has to apply a rotation transformation to the PdfCanvas counteracting the page rotation and then select the Canvas rectangle according to that rotation.