【问题标题】:Change PDFbox font of field text更改字段文本的 PDFbox 字体
【发布时间】:2019-06-27 15:34:39
【问题描述】:

我正在编写一个应用程序,它使用 PDFbox 库来填充 PDF 文件中的字段。
在其中一个字段中,我将文本设置为用希伯来字母书写。
当我在我的 Android 设备上运行代码时,我得到以下日志:

java.lang.IllegalArgumentException: This font type only supports 8-bit code points
    at com.tom_roush.pdfbox.pdmodel.font.PDType1Font.encode(PDType1Font.java:317)
    at com.tom_roush.pdfbox.pdmodel.font.PDFont.encode(PDFont.java:264)
    at com.tom_roush.pdfbox.pdmodel.font.PDFont.getStringWidth(PDFont.java:293)
    at com.tom_roush.pdfbox.pdmodel.interactive.form.PlainTextFormatter.format(PlainTextFormatter.java:183)
    at com.tom_roush.pdfbox.pdmodel.interactive.form.AppearanceGeneratorHelper.insertGeneratedAppearance(AppearanceGeneratorHelper.java:360)
    at com.tom_roush.pdfbox.pdmodel.interactive.form.AppearanceGeneratorHelper.setAppearanceContent(AppearanceGeneratorHelper.java:224)
    at com.tom_roush.pdfbox.pdmodel.interactive.form.AppearanceGeneratorHelper.setAppearanceValue(AppearanceGeneratorHelper.java:128)
    at com.tom_roush.pdfbox.pdmodel.interactive.form.PDTextField.constructAppearances(PDTextField.java:247)
    at com.tom_roush.pdfbox.pdmodel.interactive.form.PDTerminalField.applyChange(PDTerminalField.java:221)
    at com.tom_roush.pdfbox.pdmodel.interactive.form.PDTextField.setValue(PDTextField.java:202)
    at com.package.app.MainActivity.lambda$checkPdf$4$MainActivity(MainActivity.java:128)
    at com.package.app.MainActivity$$Lambda$2.run(Unknown Source:18)
    at java.lang.Thread.run(Thread.java:764)

我试图在 Stack Overflow 上找到有关它的一些信息,但我找到的答案都与填写表格无关。都和PDPageContentStream有关。

这就是我在代码中填写表格的方式:

try {
    PDDocument document = PDDocument.load(getAssets().open("file.pdf"));
    PDDocumentCatalog docCatalog = document.getDocumentCatalog();
    PDAcroForm acroForm = docCatalog.getAcroForm();

    // Fill the text field
    ((PDTextField) acroForm.getField("name")).setValue("בדיקה");

    File root = android.os.Environment.getExternalStorageDirectory();

    String path = root.getAbsolutePath() + "/test.pdf";
    document.save(path);
    document.close();
} catch (IOException e) {
    Log.e("e", e.getMessage());
}

您能帮我解决这个错误并使用 PDFbox 在表单中填写希伯来字母吗?

【问题讨论】:

  • 不知道这是否也适用于 Android 版 PDFBox,但这个答案显示了如何替换字段字体:stackoverflow.com/questions/47995062
  • @TilmanHausherr 谢谢!这真的很有帮助。我现在唯一的问题是希伯来语文本是从左到右显示的,而应该从右到左显示。你知道该怎么做吗?
  • 哎呀,我忘记了,抱歉 :-( 不,没有解决方案,甚至在桌面版 PDFBox 中也没有。你所能做的就是破解 Android 版 PDFBox 源代码,即 PlainTextFormatter 来反转字符串,当它是希伯来语并且没有任何数字或其他不是 RTL 的东西时,可能使用 icu4j。
  • @TilmanHausherr 好的,谢谢!

标签: android pdf fonts pdfbox hebrew


【解决方案1】:

我使用this answer 更改字段文本的字体。 唯一的问题是现在文本的方向不对,所以我改变了字符串的方向:

try {
    PDDocument document = PDDocument.load(getAssets().open("file.pdf"));
    PDDocumentCatalog docCatalog = document.getDocumentCatalog();
    PDAcroForm acroForm = docCatalog.getAcroForm();
    PDResources dr = acroForm.getDefaultResources();

    PDFont liberationSans = PDType0Font.load(document, getAssets().open("com/tom_roush/pdfbox/resources/ttf/LiberationSans-Regular.ttf"));
    COSName fontName = dr.add(liberationSans);
    Iterator<PDField> it = acroForm.getFields().iterator();
    while (it.hasNext()) {
        PDField field = it.next();
        if (field instanceof PDTextField) {
            PDTextField textField = (PDTextField) field;
            String da = textField.getDefaultAppearance();

            // replace font name in default appearance string
            Pattern pattern = Pattern.compile("\\/(\\w+)\\s.*");
            Matcher matcher = pattern.matcher(da);
            String oldFontName = matcher.group(1);
            da = da.replaceFirst(oldFontName, fontName.getName());

            textField.setDefaultAppearance(da);
        }
    }

    // Fill the text field
    ((PDTextField) acroForm.getField("name")).setValue(new StringBuilder("בדיקה").reverse().toString());

    File root = android.os.Environment.getExternalStorageDirectory();

    String path = root.getAbsolutePath() + "/test.pdf";
    document.save(path);
    document.close();
} catch (IOException e) {
    Log.e("e", e.getMessage());
}

【讨论】:

  • 但现在的问题是该字段的逻辑内容也颠倒了——这在计算机读取表单时很重要。一种可能的解决方案是使用 field.getCOSObject().setString(COSName.V, string) 对原始字符串进行低级重新分配。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-10-20
  • 1970-01-01
  • 2011-09-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-21
相关资源
最近更新 更多