使用 iText 自定义签名外观

Custom signature appearance using iText

我正在尝试使用 iText(sharp,版本 5.5.13)创建自定义数字签名,用户可以在其中从一组四个位置(顶部、底部、左侧和右侧)设置图像位置,如如下所示:

右:

左:

顶部:

底部:

到目前为止,我尝试处理签名的第 0 层,但我认为我做错了,因为签名详细信息是在第 2 层中设置的。

然而,这只是设置图像位置的初始草图。在下面的代码中,我加载图像并将其放入一个块中(想法取自此example

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();

结果和预期的差不多,但是有两个问题:签名信息占据了整个矩形(这是正常的,因为我没有修改layer 2,layer 0的图像没有缩放为应该)

如果我缩放图像以适合该列,它会到达矩形的顶部:

有什么方法可以做到这一点"out of the box"或者我需要重载构建签名外观的方法(like this),我该如何实现?

我最初的音乐会没有使用 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;
    }
}

这将产生以下签名:

当然,它仍然需要一些改进,但它可以作为其他人的榜样:-)