c# - 使用 iText 自定义签名外观
问题描述
我正在尝试使用 iText(sharp,5.5.13 版)创建自定义数字签名,用户可以从一组四个位置(顶部、底部、左侧和右侧)设置图像位置,如下所示:
正确:
剩下:
最佳:
底部:
到目前为止,我尝试处理签名的第 0 层,但我认为我做错了,因为签名详细信息设置在第 2 层。
然而,这只是设置图像位置的初始草图。在下面的代码中,我加载图像并将其放入一个块中(取自此示例的想法)
PdfTemplate pdfTemplate = sap.GetLayer(0);
ColumnText c1 = new ColumnText(pdfTemplate);
Image img = Image.GetInstance(signatureImage);
Phrase elements = new Phrase();
elements.Add(new Chunk(img, 0, 0, true));
//c1.SetSimpleColumn(elements, 0, 0, rectangle.Width, rectangle.Height / 4, 0, Element.ALIGN_CENTER); // align bottom
//c1.SetSimpleColumn(elements, 0, rectangle.Height / 2, rectangle.Width, rectangle.Height, 0, Element.ALIGN_CENTER); // align top
c1.SetSimpleColumn(elements, rectangle.Width/2, 0, rectangle.Width, rectangle.Height, 0, Element.ALIGN_CENTER); // align right
//c1.SetSimpleColumn(elements, 0, 0, rectangle.Width/2, rectangle.Height, 0, Element.ALIGN_CENTER); // align left
c1.Go();
结果或多或少是预期的,但有两个问题:签名信息占据了整个矩形(这是正常的,因为我没有修改第 2 层,第 0 层中的图像没有按应有的比例缩放)
如果我缩放图像以适合列,它会转到矩形的顶部:
有什么方法可以“开箱即用”,或者我需要重载构建签名外观的方法(像这样),我该如何实现?
解决方案
我最初的音乐会不是使用 iText (v7),因为我们没有太多时间来迁移我们使用 iText (v5) 拥有的所有项目,但我继续尝试使用 v7。但老实说,用 v5 似乎不太容易实现。
另一方面,在 iText (v7) 中,我可以用这个简单的方法很快地做到这一点:
private static void SetCustomSignature(PdfDocument doc, PdfSignatureAppearance sap, SignatureFormat signatureFormat, X509Certificate2 signerCertificate) {
string signatureFont = signatureFormat.Font;
float signatureFontSize = float.Parse(signatureFormat.FontSize);
Rectangle rect = new Rectangle(250, 100, 200, 80);
sap.SetPageRect(rect).SetPageNumber(1);
PdfFormXObject layer2 = sap.GetLayer2();
PdfCanvas canvas = new PdfCanvas(layer2, doc);
float MARGIN = 2;
PdfFont font = PdfFontFactory.CreateFont();
string signingText = GetSignatureInfo(signerCertificate, signatureFormat);
// Signature at left and image at right
//Rectangle dataRect = new Rectangle(rect.GetWidth() / 2 + MARGIN / 2, MARGIN, rect.GetWidth() / 2 - MARGIN, rect.GetHeight() - 2 * MARGIN);
//Rectangle signatureRect = new Rectangle(MARGIN, MARGIN, rect.GetWidth() / 2 - 2 * MARGIN, rect.GetHeight() - 2 * MARGIN);
// Signature at right and image at left
//Rectangle dataRect = new Rectangle(MARGIN, MARGIN, rect.GetWidth() / 2 - MARGIN, rect.GetHeight() - 2 * MARGIN);
//Rectangle signatureRect = new Rectangle(rect.GetWidth() / 2 + MARGIN / 2, MARGIN, rect.GetWidth() / 2 - 2 * MARGIN, rect.GetHeight() - 2 * MARGIN);
// Signature at top and image at bottom
//Rectangle dataRect = new Rectangle(MARGIN, MARGIN, rect.GetWidth() - 2 * MARGIN, rect.GetHeight() / 2 - MARGIN);
//Rectangle signatureRect = new Rectangle(MARGIN, rect.GetHeight() / 2 + MARGIN, rect.GetWidth() - 2 * MARGIN, rect.GetHeight() / 2 - MARGIN);
// Signature at bottom and image at top
Rectangle dataRect = new Rectangle(MARGIN, rect.GetHeight() / 2 + MARGIN, rect.GetWidth() - 2 * MARGIN, rect.GetHeight() / 2 - MARGIN);
Rectangle signatureRect = new Rectangle(MARGIN, MARGIN, rect.GetWidth() - 2 * MARGIN, rect.GetHeight() / 2 - MARGIN);
try {
Canvas signLayoutCanvas = new Canvas(canvas, doc, signatureRect);
Paragraph paragraph = new Paragraph(signingText).SetFont(font).SetMargin(0).SetMultipliedLeading(0.9f).SetFontSize(10);
Div div = new Div();
div.SetHeight(signatureRect.GetHeight());
div.SetWidth(signatureRect.GetWidth());
div.SetVerticalAlignment(iText.Layout.Properties.VerticalAlignment.MIDDLE);
div.SetHorizontalAlignment(iText.Layout.Properties.HorizontalAlignment.CENTER);
div.Add(paragraph);
signLayoutCanvas.Add(div);
Canvas dataLayoutCanvas = new Canvas(canvas, doc, dataRect);
Image image = new Image(ImageDataFactory.Create(signatureFormat.SignatureImage));
image.SetAutoScale(true);
Div dataDiv = new Div();
dataDiv.SetHeight(dataRect.GetHeight());
dataDiv.SetWidth(dataRect.GetWidth());
dataDiv.SetVerticalAlignment(iText.Layout.Properties.VerticalAlignment.MIDDLE);
dataDiv.SetHorizontalAlignment(iText.Layout.Properties.HorizontalAlignment.CENTER);
dataDiv.Add(image);
dataLayoutCanvas.Add(dataDiv);
}
catch {
throw;
}
}
这将产生以下签名:
当然,它仍然需要一些改进,但它可以作为其他人的榜样:-)