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?
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);
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.
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:
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.
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:
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.
Thanks for the response. I will wait for your response on USING CUSTOM SIGNATURE part.
Thankyou very much for the solution. It worked like a charm :). There is one thing I am getting issue about that the final appearance on 270 and 90 degree rotated documents feels like zoomed out. I tried to fix the issue by changing the width and height values but the issue is not resolved. For reference I have attached an image in the question. Could you please guide me in this scenario. Regards
I'll look into that next week.
I had a look at your new screen shots. I don't understand what you mean by "feels like zoomed out" on them. Can you explain? Probably by showing a sketch of what you would expect instead on those screen shots?
I menat by "feels like zoomed out" that the signature appearance rendered as per desired results after applying the solution provided by you but the signature appearance content is much smaller than the signature field size and as shown in the image I have attached. The black border is the size of signature field and If you see the signature appearance content, it is much smaller than the field size rather to be fit according to the field size. Regards