代码之家  ›  专栏  ›  技术社区  ›  Egl

第2层签名外观字体颜色(itext 7)

  •  1
  • Egl  · 技术社区  · 7 年前

    我正在尝试使用iText7 7.1.0(java)中的字体颜色生成外观为的签名。

    使用iText5,调用时包括fontColor FontFactory.getFont() ,然后:

    Font font = FontFactory.getFont(fontName, encoding, embedFont, fontSize, style, bColor); 
    appearance.setLayer2Font(font); 
    

    但是,在iText7中,字体似乎丢失了fontSize和fontColor信息。 有一个新的 appearance.setLayer2FontSize() fontSize的方法。 但我无法找到指示第二层字体颜色的方法。

    我在分类文本或段落中发现了setFontColor。

    但是,在生成SignaturePerance时,要调用的方法似乎是 PdfSignatureAppearance.setLayer2Text(String) ,参数只是一个字符串。

    如何在iText7中修改layer2字体颜色?

    提前非常感谢。

    2 回复  |  直到 7 年前
        1
  •  2
  •   mkl    7 年前

    显然,在移植时,没有考虑在iText 5字体对象中传输颜色的选项 PdfSignatureAppearance 从iText 5到iText 7,至少我看不到任何官方方法可以将所需的颜色传输到外观创建过程中。

    在这种情况下,明显的选择是手动创建第2层。这样,您就可以根据需要设计外观了。您可以复制(&A);粘贴原始代码,包括从原始iText设计开始设计所需的隐藏助手方法。

    如果您不想这样做,也就是说,如果您仍然希望iText创建外观并只是稍微调整一下,那么有一个解决方法:您可以让iText创建外观,然后稍微操纵一下。

    不幸的是,这现在需要作为 PDF签名外观 生成外观的方法, getAppearance() protected . (过去是 public 在iText 5…)中

    如果您对这种解决方法没有意见,可以如下所示对文本进行着色:

    PdfSigner signer = ...;
    PdfSignatureAppearance appearance = signer.getSignatureAppearance();
    
    [... customize the appearance using its usual methods ...]
    
    // call appearance.getAppearance() using reflection
    // this initializes the layers in the appearance object
    Method getAppearanceMethod = PdfSignatureAppearance.class.getDeclaredMethod("getAppearance");
    getAppearanceMethod.setAccessible(true);
    getAppearanceMethod.invoke(appearance);
    
    // add a fill color setting instruction
    // at the start of layer 2
    PdfFormXObject layer2 = appearance.getLayer2();
    PdfStream layer2Stream = layer2.getPdfObject();
    byte[] layer2Bytes = layer2Stream.getBytes();
    layer2Stream.setData("1 0 0 rg\n".getBytes());
    layer2Stream.setData(layer2Bytes, true);
    
    signer.signDetached(...);
    

    ( CreateSpecialSignatureAppearance 试验方法 testColorizeLayer2Text )

    由于最初生成的外观中的填充颜色未显式设置,但默认为黑色,因此此前置指令会将所有文本着色为红色(使用具有100%红色、0%绿色和0%蓝色的RGB颜色)。


    事实上,我有点惊讶,iText 7仍然携带着所有这些签名层的东西。至少自ISO 32000-1于2008年发布以来,除了支持Adobe viewer特定的行为之外,再也没有理由使用这些层了,甚至Adobe自己在ISO 32000-1发布前几年就已经声明不赞成这些行为。

    是否有这么大的利益集团游说支持这些不受欢迎的行为?

        2
  •  0
  •   Zoran777    3 年前

    您可以使用这种方式创建自定义图层2,然后向其添加修改。

    // Create the signature appearance
                Rectangle rect = new Rectangle(36, 50, 200, 100);
                PdfSignatureAppearance appearance = signer.getSignatureAppearance();
                appearance
                .setLocation(location)
    
                // Specify if the appearance before field is signed will be used
                // as a background for the signed field. The "false" value is the default value.
                .setReuseAppearance(false)
                .setPageRect(rect)
                .setPageNumber(r.getNumberOfPages());
                signer.setFieldName("sig");
                
                appearance.setLayer2Font(PdfFontFactory.createFont(StandardFonts.TIMES_ITALIC));
                
                // Get the background layer and draw a gray rectangle as a background.
                PdfFormXObject n0 = appearance.getLayer0();
                float x = n0.getBBox().toRectangle().getLeft();
                float y = n0.getBBox().toRectangle().getBottom();
                float width = n0.getBBox().toRectangle().getWidth();
                float height = n0.getBBox().toRectangle().getHeight();
                PdfCanvas canvas = new PdfCanvas(n0, signer.getDocument());
                canvas.setFillColor(ColorConstants.CYAN);
                canvas.rectangle(x, y, width, height);
                canvas.fill();
    
                // Set the signature information on layer 2
                PdfFormXObject n2 = appearance.getLayer2();
                Paragraph p = new Paragraph("This document was signed by Bruno Specimen.");
                new Canvas(n2, signer.getDocument()).add(p);
    
                // Creating the signature
                IExternalSignature pks = new PrivateKeySignature(pk, digestAlgorithm, provider);
                IExternalDigest digest = new BouncyCastleDigest();