z如何更改 pdfbox Java 中现有 PDTextField 的字体?

问题描述 投票:0回答:1

我正在使用一个包含文本表单的 pdf 模板。我的程序需要将文本插入这些表单中。出现问题的原因是插入文本是捷克语。我知道我需要安装特殊字体才能使用捷克语:

PDFont formFont = PDType0Font
        .load(doc,
              PDFGenerator.class.getResourceAsStream(
                      "/fonts/AbhayaLibre-Regular.ttf"),
              false);

PDAcroForm acroForm = doc.getDocumentCatalog().getAcroForm();
PDResources resources = acroForm.getDefaultResources();
String fontName = resources.add(formFont).getName();

字体设置为这样的字段:

PDTextField template = (PDTextField) acroForm.getField("main_text");
template.setMultiline(template.isMultiline());
template.setDefaultAppearance(template.getDefaultAppearance()
                                      .replaceAll("/\\w+", "/"
                                                           + fontName));
template.setValue("Ahoj světe");

例如,此代码适用于在 LibreOffice 中创建的模板。但对于在 https://www.sejda.com/pdf-forms 中创建的模板,它会因编码错误而崩溃

线程“main”中的异常 java.lang.IllegalArgumentException:U+011B('ecaron')在 Helvetica 字体中不可用,编码:WinAnsiEncoding 在 org.apache.pdfbox.pdmodel.font.PDType1Font.encode(PDType1Font.java:410) 在 org.apache.pdfbox.pdmodel.font.PDFont.encode(PDFont.java:337)

我可以在程序中创建新的PDTextField,为其设置字体和矩形。然后程序就可以正常运行了

PDFont formFont = PDType0Font
        .load(doc,
              PDFGenerator.class.getResourceAsStream(
                      "/fonts/AbhayaLibre-Regular.ttf"),
              false);


PDAcroForm acroForm = doc.getDocumentCatalog().getAcroForm();
PDResources resources = acroForm.getDefaultResources();
final String fontName = resources.add(formFont).getName();

PDPage page = doc.getPage(0);
PDTextField template = (PDTextField) acroForm.getField("main_text");
PDTextField implementation = new PDTextField(acroForm);

implementation.setPartialName(
        template.getPartialName() + "_generated");
implementation.setMultiline(template.isMultiline());
implementation.setDefaultAppearance(template.getDefaultAppearance()
                                            .replaceAll("/\\w+", "/"
                                                                 + fontName));
implementation.getWidgets().get(0).setRectangle(
        template.getWidgets().get(0).getRectangle());
implementation.getWidgets().get(0).setPage(page);
implementation.setValue("Ahoj světe");
page.getAnnotations().add(implementation.getWidgets().get(0));
acroForm.getFields().add(implementation);

template.setReadOnly(true);
template.setValue(null);

doc.save("1.pdf");

我认为此行为是由于 DefaultAppearance 与 pdf 编辑器设置的值重叠所致,但我不知道在哪里寻找它。 我的推理正确吗?在pdfbox表单主体中处理外语的正确方法是什么?

将文件放入光盘。 https://drive.google.com/drive/folders/14Ko_55T9wyYaC6rj7uoH5AUYcTOgN7JC?usp=sharing *_new_font - 之后创建的文件

template.setDefaultAppearance(template.getDefaultAppearance()
                                      .replaceAll("/\\w+", "/"
                                                           + fontName));

执行。

我尝试调试默认外观更改,发现在 setDefaultAppearance 之后字段的默认外观发生了更改,而小部件的默认外观可能不会更改。

System.out.println("Old field default appearance: "
                   + template.getDefaultAppearance());
System.out.println("Old widget default appearance: "
                   + template.getWidgets().get(0).getCOSObject()
                             .getString(COSName.DA));
String newAppearance = template.getDefaultAppearance()
                               .replaceAll("/\\w+", "/"
                                                    + fontName);
template.setDefaultAppearance(newAppearance);
System.out.println("Nef field default appearance: "
                   + template.getDefaultAppearance());
System.out.println("New widget default appearance: "
                   + template.getWidgets().get(0).getCOSObject()
                             .getString(COSName.DA));

这个代码给出了seiga

Old field default appearance: /Helv 18 Tf 0.129 0.129 0.129 rg
Old widget default appearance: /Helv 18 Tf 0.129 0.129 0.129 rg
Nef field default appearance: /F3 18 Tf 0.129 0.129 0.129 rg
New widget default appearance: /Helv 18 Tf 0.129 0.129 0.129 rg

为了自由

Old field default appearance: 1 1 1 rg /He 10.006 Tf
Old widget default appearance: 1 1 1 rg /He 10.006 Tf
Nef field default appearance: 1 1 1 rg /F4 10.006 Tf
New widget default appearance: 1 1 1 rg /F4 10.006 Tf

我可以在更改字段的外观之前删除小部件的 DA。这将解决我的问题。 不过,我还有疑问:

  1. 为什么 setDefault 外观有时会改变 widget 的 DA,有时不会?
  2. 有没有办法设置字段的外观,以便其他对象无法覆盖它?
  3. 除了 Widget 之外,还有哪些对象可以覆盖字段的外观?

我使用的是pdfbox 3.0.2

java pdf fonts pdf-generation pdfbox
1个回答
0
投票

正如 Tilman Hausherr 所评论的,当文件的小部件拥有自己的 DA 时,就会出现问题。解决这个问题的正确方法是在更改字体之前从 widget 中删除 DA

String newAppearance = template.getDefaultAppearance()
                               .replaceAll("/\\w+", "/"
                                                    + fontName);
template.getWidgets().get(0).getCOSObject().removeItem(COSName.DA);
template.setDefaultAppearance(newAppearance);
© www.soinside.com 2019 - 2024. All rights reserved.