Search code examples
javaitextitext7

Signature appearance font color in layer2 (itext 7)


I'm trying to generate a signature with appearance using a font color in iText7 7.1.0 (java).

Using iText5, the fontColor was included when calling to FontFactory.getFont(), then:

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

But, in iText7 it seems Font has lost fontSize and fontColor information. There's a new appearance.setLayer2FontSize() method for fontSize. But I'm not able to find the way to indicate the layer2 font color.

I've found a setFontColor in clases Text or Paragraph.

But, when generating a signatureApperance, the method to be called seems to be PdfSignatureAppearance.setLayer2Text(String), the argument is just an String.

How can I modify layer2 font color in iText7 ?

Thanks a lot in advance.


Solution

  • Apparently the option to transport a color in an iText 5 font object has not been considered when porting the PdfSignatureAppearance from iText 5 to iText 7, at least I don't see any official way to transport the desired color into the appearance creation process.

    The obvious choice in such a situation is to create a layer 2 manually. Doing so you have all options to design the appearance as you want. And you can copy&paste the original code including required hidden helper methods to start your design from the original iText design.

    If you don't want to do so, i.e. if you still want iText to create the appearances and merely tweak it a bit, there is a work-around: You can ask iText to create the appearances and then manipulate them a bit.

    Unfortunately this now requires reflection as the PdfSignatureAppearance method for generating the appearances, getAppearance(), is protected. (It used to be public in iText 5...)

    If you are ok with such a work-around, you can colorize your text like this:

    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 test method testColorizeLayer2Text)

    As the fill color in the originally generated appearance is not explicitly set but black by default, this prepended instruction colorizes all text red (using an RGB color with 100% red, 0% green, and 0% blue).


    I'm actually a bit surprised that iText 7 still carries all this signature layer stuff around. At least since ISO 32000-1 was published in 2008, there was no reason to use those layers anymore other than to support Adobe viewer specific behavior which even Adobe themselves had declared deprecated years before ISO 32000-1.

    Is there such a large interest group lobbying in favor of those deprecated behaviors?