Java PDFBox configures custom font for multiple fields in PDF

I am using Apache PDFBox to read a fillable PDF form and fill in fields based on some data. I am using the below code (as suggested from other SO answers) to get the default appearance string and change it (as you can see below, I change the font size from 10 to 12 if field is "Field1".

  • How do I highlight a field? Any documentation what order is / Helv 10 Tf 0 g in? What do I need to bold a field?
  • If I understand correctly, there are 14 basic fonts that I can use in the PDFBox out of the box (pun intended inadvertently). I would like to use one or more fonts that look like Signatures (cursive). Any of the fonts that do this? If not, if I have my own font, how do I set in the method to be written to PDF?

Note that the code below works great by filling in the specific value passed in the method parameter in the specific "name" field of the method parameter.

Thank!

public static void setField(String name, String value ) throws     IOException {
    PDDocumentCatalog docCatalog = _pdfDocument.getDocumentCatalog();
    PDAcroForm acroForm = docCatalog.getAcroForm();
    PDField field = acroForm.getField( name );

    COSDictionary dict = ((PDField)field).getDictionary();
    COSString defaultAppearance = (COSString) dict.getDictionaryObject(COSName.DA);
    if (defaultAppearance != null)
    {
        dict.setString(COSName.DA, "/Helv 10 Tf 0 g");
        if(name.equalsIgnoreCase("Field1"))
        {
            dict.setString(COSName.DA, "/Helv 12 Tf 0 g");
        }
    }
    if(field instanceof PDTextbox)
    {
        field= new PDTextbox(acroForm, dict);
        ((PDField)field).setValue(value);
    }

      

As per mkl's answer, to use two fonts in one PDF, I used the following method, I couldn't get the default font and my own font working together, so I added the two fonts to the resources and used them.

public List<String> prepareFont(PDDocument _pdfDocument) throws IOException
{
    PDDocumentCatalog docCatalog = _pdfDocument.getDocumentCatalog();
    PDAcroForm acroForm = docCatalog.getAcroForm();

    PDResources res = acroForm.getDefaultResources();
    if (res == null)
        res = new PDResources();

    InputStream fontStream = getClass().getResourceAsStream("LiberationSans-Regular.ttf");
InputStream fontStream2 = getClass().getResourceAsStream("Font2.ttf");
    PDTrueTypeFont font = PDTrueTypeFont.loadTTF(_pdfDocument, fontStream);
PDTrueTypeFont font2 = PDTrueTypeFont.loadTTF(_pdfDocument, fontStream2);
    String fontName = res.addFont(font); 
String fontName2 = res.addFont(font2);
    acroForm.setDefaultResources(res);
    List<String> fontList = new ArrayList<String>();    fontList.add(font1);fontList.add(font2);
    return fontList;
}

      

+3


source to share


1 answer


(You can find an example execution here: FillFormCustomFont.java )

Using poor people

  • How do I highlight a field? ... What do I need to make a field bold?

In PDF, you usually make the text bold, using a font with bold glyphs, see also the second question. If you don't have this bold type on hand, you can instead use some white man technique, for example. not only filling in the letter, but also stroking the line along its borders:

public static void setFieldBold(String name, String value) throws IOException
{
    PDDocumentCatalog docCatalog = _pdfDocument.getDocumentCatalog();
    PDAcroForm acroForm = docCatalog.getAcroForm();
    PDField field = acroForm.getField(name);

    COSDictionary dict = ((PDField) field).getDictionary();
    COSString defaultAppearance = (COSString) dict
            .getDictionaryObject(COSName.DA);
    if (defaultAppearance != null)
    {
        dict.setString(COSName.DA, "/Helv 10 Tf 2 Tr .5 w 0 g");
        if (name.equalsIgnoreCase("Field1")) {
            dict.setString(COSName.DA, "/Helv 12 Tf 0 g");
        }
    }
    if (field instanceof PDTextbox)
    {
        field = new PDTextbox(acroForm, dict);
        ((PDField) field).setValue(value);
    }
}

      

( 2 Tr .5 w

= use render mode 2, i.e. fill and stroke, and use line width .5)

Instead

Using the OP's method

now you get

Using the setFieldBold method

Using custom fonts

  1. If I understand correctly, there are 14 basic fonts that I can use in the PDFBox out of the box (pun intended inadvertently). I would like to use one or more fonts that look like Signatures (cursive). Any of the fonts that do this? If not, if I have my own font, how do I set in the method to be written to PDF?

If you want to use a custom font, you first need to register it with the AcroForm default assets , for example:

public String prepareFont(PDDocument _pdfDocument) throws IOException
{
    PDDocumentCatalog docCatalog = _pdfDocument.getDocumentCatalog();
    PDAcroForm acroForm = docCatalog.getAcroForm();

    PDResources res = acroForm.getDefaultResources();
    if (res == null)
        res = new PDResources();

    InputStream fontStream = getClass().getResourceAsStream("LiberationSans-Regular.ttf");
    PDTrueTypeFont font = PDTrueTypeFont.loadTTF(_pdfDocument, fontStream);
    String fontName = res.addFont(font);
    acroForm.setDefaultResources(res);

    return fontName;
}

      

This method returns the name of the font to use in

public static void setField(String name, String value, String fontName) throws IOException
{
    PDDocumentCatalog docCatalog = _pdfDocument.getDocumentCatalog();
    PDAcroForm acroForm = docCatalog.getAcroForm();
    PDField field = acroForm.getField(name);

    COSDictionary dict = ((PDField) field).getDictionary();
    COSString defaultAppearance = (COSString) dict
            .getDictionaryObject(COSName.DA);
    if (defaultAppearance != null)
    {
        dict.setString(COSName.DA, "/" + fontName + " 10 Tf 0 g");
        if (name.equalsIgnoreCase("Field1")) {
            dict.setString(COSName.DA, "/" + fontName + " 12 Tf 0 g");
        }
    }
    if (field instanceof PDTextbox)
    {
        field = new PDTextbox(acroForm, dict);
        ((PDField) field).setValue(value);
    }
}

      

Now you get

Using the setFieldBold method with font parameter

The difference is not too big because the fonts are very similar. Use a font of your choice for more effect.

Using / Helv , / HeBo , ...



The OP found a list of font names / Helv , / HeBo , ..., possibly in the PDFBox PDFBOX-1234 release , which apparently can be used without defining them in any resource dictionary.

These names are not a PDF feature , i.e. the PDF spec doesn't know about them, on the contrary:

The appearance bar ( DA ) contains any graphic state states or text statements required to set graphic state parameters, such as text size and color, to display variable variable text. This line should contain only those operators that are allowed in text objects (see Fig. 9). At a minimum, the string must include a Tf (text font) operator along with two operands, font and size. The specified font value must match the resource name in the Font entry of the default resource dictionary (link to the DR entry of the interactive form word), see Table 218).

(Section 12.7.3.3 Field Dictionaries / Variable Text in ISO 32000-1)

Thus, the spec doesn't know these default font names.

However, Adobe Reader / Acrobat seems to support them, most likely because at some point in the distant past some form shaping tool assumed they existed, and support for these forms was retained due to compatibility reasons. ...

Using this feature, therefore, may not be the best choice, but your mileage may vary.

Using custom and standard fonts

In his comments, the OP indicated that he wanted to use both standard and standard fonts in forms.

To do this, I generalized the method a bit prepareFont

and refactored the TTF import into a separate method:

public List<String> prepareFont(PDDocument _pdfDocument, List<PDFont> fonts) throws IOException
{
    PDDocumentCatalog docCatalog = _pdfDocument.getDocumentCatalog();
    PDAcroForm acroForm = docCatalog.getAcroForm();

    PDResources res = acroForm.getDefaultResources();
    if (res == null)
        res = new PDResources();

    List<String> fontNames = new ArrayList<String>();
    for (PDFont font: fonts)
    {
        fontNames.add(res.addFont(font));
    }

    acroForm.setDefaultResources(res);

    return fontNames;
}

public PDFont loadTrueTypeFont(PDDocument _pdfDocument, String resourceName) throws IOException
{
    try ( InputStream fontStream = getClass().getResourceAsStream(resourceName); )
    {
        return PDTrueTypeFont.loadTTF(_pdfDocument, fontStream);
    }
}

      

Using these methods, you can mix standard and standard fonts such as:

PDDocument doc = PDDocument.load(originalStream);
List<String> fontNames = prepareFont(doc, Arrays.asList(loadTrueTypeFont(doc, "LiberationSans-Regular.ttf"), PDType1Font.HELVETICA_BOLD));

setField(doc, "FirstName", "My first name", fontNames.get(0));
setField(doc, "LastName", "My last name", fontNames.get(1));

doc.save(new File(RESULT_FOLDER, "acroform-setFieldCustomStandard.pdf"));
doc.close();

      

( FillFormCustomFont .testSetFieldCustomStandard_acroform)

Result

Using mixed custom and standard fonts

PDType1Font

has constants for all 14 standard fonts. This way, you can use standard fonts (mixed with custom fonts if required) in form fields in such a way as to generate correct Font entries in default resources, that is, not relying on the brand names of the default fonts like HEBO .

PS

Any documentation in what order / Helv 10 Tf 0 g are posted?

Yes, there is, cf. ISO 32000-1 specification .

+11


source







All Articles