java pdf 用系统字体大小,Java PDFBox为PDF表单中的几个字段设置自定义字体

这篇博客介绍了如何使用Apache PDFBox库填充PDF表单并更改字体大小。作者展示了如何根据字段名称改变字体大小,并探讨了如何加粗字体。通过设置DA(默认外观字符串),可以调整字体大小和样式。此外,还讨论了如何使用自定义字体和PDFBox内置的14种字体之一来创建类似手写签名的样式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

How do I bold the field? Any documentation on what order the /Helv 10 Tf 0 g are arranged? What I need to set to bold the field?

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

Please note, the below code works fine by filling the specific 'value' passed in the method parameter in the specific 'name' field of the method parameter.

Thank you !

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 the same PDF, I used the following method: I could not get the default font and a custom font working together, so I added two fonts to the resources and used them.

public List 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 fontList = new ArrayList(); fontList.add(font1);fontList.add(font2);

return fontList;

}

解决方案

(You can find a runnable example here: FillFormCustomFont.java)

Using poor-man's-bold

How do I bold the field? ... What I need to set to bold the field?

In PDF you usually make text bold by using a font with bold glyphs, also see your second question. If you don't have such a bold font at hands, you may instead use some poor-man's-bold technique, e.g. not only filling the letter but also stroking a 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 rendering mode 2, i.e. fill and stroke, and use a line width of .5)

Instead of

fpbbS.png

you now get

BD2AE.png

Using custom fonts

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

If you want to use an own font, you first need to register it in the AcroForm default resources like this:

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 font name 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);

}

}

You now get

cQiEN.png

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

Using /Helv, /HeBo, ...

The OP found a list of font names /Helv, /HeBo, ..., probably in the PDFBox issue PDFBOX-1234, which appear to be usable without defining them in any resource dictionary.

These names are not a PDF feature, i.e. the PDF specification does not know about them, on the contrary:

The default appearance string (DA) contains any graphics state or text state operators needed to establish the graphics state parameters, such as text size and colour, for displaying the field’s variable text. Only operators that are allowed within text objects shall occur in this string (see Figure 9). At a minimum, the string shall include a Tf (text font) operator along with its two operands, font and size. The specified font value shall match a resource name in the Font entry of the default resource dictionary (referenced from the DR entry of the interactive form dictionary; see Table 218).

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

Thus, the specification does not know those default font names.

Nonetheless, Adobe Reader/Acrobat seem to support them, most likely because at some time in the distant past some form generating tool assumed them to be there and support for those forms was kept due to compatibility reasons.

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

Using custom and standard fonts

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

To do this I generalized the method prepareFont a bit and refactored the TTF import into a separate method:

public List prepareFont(PDDocument _pdfDocument, List fonts) throws IOException

{

PDDocumentCatalog docCatalog = _pdfDocument.getDocumentCatalog();

PDAcroForm acroForm = docCatalog.getAcroForm();

PDResources res = acroForm.getDefaultResources();

if (res == null)

res = new PDResources();

List fontNames = new ArrayList();

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 custom and standard fonts like this:

PDDocument doc = PDDocument.load(originalStream);

List 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)

Resulting in

EfFwP.png

PDType1Font has constants for all 14 standard fonts. Thus, like this you can use standard fonts (mixed with custom fonts if desired) in form fields in a way that generates the proper Font entries in the default resources, i.e. without relying on proprietary default font names like HeBo.

PS

Any documentation on what order the /Helv 10 Tf 0 g are arranged?

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值