当前位置: 首页 > 知识库问答 >
问题:

用PDFBox嵌入FlateDPDF表单的字体

罗绪
2023-03-14

我用PDFBox填写一个PDF表单,我在保存它之前把它变平。窗体具有文本和窗体字段的自定义字体。当我在未安装此自定义字体的设备上打开输出文档(具有平坦字段)时,普通文本的字体仍然正确,但平坦字段的字体显示为回退(?)字体。在安装了这种自定义字体的设备上,一切看起来都和预期的一样。

有没有办法在展平窗体后,强制对所有文本使用相同的自定义字体?

使用PDFBOX填写PDF表单时使用的代码(简化):

public class App
{
    public static void main(String[] args) throws IOException {
        String formTemplate = "src/main/resources/fonts.pdf";
        String filledForm = "src/main/resources/fonts_out.pdf";
        PDDocument pdfDocument = PDDocument.load(new File(formTemplate));
        PDAcroForm acroForm = pdfDocument.getDocumentCatalog().getAcroForm();
        acroForm.getField("text").setValue("Same font in form text field (updated with PDFBox)");
        acroForm.setNeedAppearances(true);
        acroForm.refreshAppearances();
        acroForm.flatten();
        pdfDocument.save(filledForm);
        pdfDocument.close();
    }
}

共有1个答案

堵恺
2023-03-14

对您的PDF文件的一些观察(上面提到的编码问题不是--只是我完全不知道):

>

  • SansDroid字体未嵌入PDF。通过将F2字体替换为新嵌入的F5字体,可以修复此问题。

    NeedExceptions标志的设置意味着表单字段没有外观。任何读者都必须(重新)创建这些。这不是由PDFBox自动完成的,在平面化之前,所以我添加了这个部分

    我通过预置运行原始PDF,它给我以下警告:“所需的键/子类型丢失。路径:->Pages->Kids->[0]->Annots->[0]->AP->N”键确实存在,但似乎暗示表单字段的外观有错误。如果我删除/n指示,错误就会消失。流是“/TX BMC EMC”--也许缺少一些EOL?但是,由于外观无论如何都是重新生成的,错误随后就消失了。

    通过以下代码,DroidSans字体嵌入到PDF中:

    File pdf = new File("Fonts.pdf");
    final PDDocument document = PDDocument.load(pdf);
    
    FileInputStream fontFile = new FileInputStream(new File("DroidSans.ttf"));
    PDFont font = PDType0Font.load(document, fontFile, false);
    
    //1. embedd and register the font (Catalog dict)
    PDAcroForm pDAcroForm = document.getDocumentCatalog().getAcroForm();
    //create a new font resource
    PDResources res = pDAcroForm.getDefaultResources();
    if (res == null) res = new PDResources();
    COSName fontName = res.add(font);
    pDAcroForm.setDefaultResources(res);
    
    //2. Now change the font of form field to the newly added font
    PDField field = pDAcroForm.getField("text");
    //field.setValue("Same font in form text field (updated with PDFBox)");
    
    COSDictionary dict = field.getCOSObject();
    COSString defaultAppearance = (COSString) dict.getDictionaryObject(COSName.DA);
    
    if (defaultAppearance != null){
        String currentValue = dict.getString(COSName.DA);
        //replace the font - this should be improved with a more general version
        dict.setString(COSName.DA,currentValue.replace("F2", fontName.getName()));
    
        //remove F2 completely
        COSDictionary resources = res.getCOSObject();
        for(Entry<COSName, COSBase> resource : resources.entrySet()) {
            if(resource.getKey().equals(COSName.FONT)) {
                COSObject fonts = (COSObject)resource.getValue();
                COSDictionary fontDict = (COSDictionary)fonts.getObject();
    
                COSName toBeRemoved=null;
                for(Entry<COSName, COSBase> item : fontDict.entrySet()) {
                    if(item.getKey().getName().equals("F2")) {
                        toBeRemoved = item.getKey();
                    }
                }
                if(toBeRemoved!=null) {
                    fontDict.removeItem(toBeRemoved);
                }
            }
        }
    
    if(pDAcroForm.getNeedAppearances()) {
        pDAcroForm.refreshAppearances();
        pDAcroForm.setNeedAppearances(false);
    }
    
    //Flatten the document
    pDAcroForm.flatten();
    
    //Save the document
    document.save("Form-Test-Result.pdf");
    document.close();
    

    请注意,上面的代码是相当静态的--搜索和替换一个名为f2的字体只对提供的PDF有效,在其他情况下则不行。你必须实现一个更通用的解决方案...

  •  类似资料:
    • 请,我想知道从pdf中提取的字体是否嵌入,如何使用PDFBox实现这一点?

    • 我正在使用PDFBox从现有的PDF模板构建文档,因此它会打开文件,向其中添加文本,然后保存。除了尝试使用外部TTF字体外,它工作得很好。我尝试了不同的方法,花了两天时间寻找解决方案,但PDFBox上没有太多。 这里有一些代码,使用字体“Tardy Kid”,因为它不能被误认为其他任何东西,也不太可能是任何标准库的一部分。 代码执行良好,显示println中的“TardyKid”(显示字体已加载且

    • 我正在使用pdfbox 2.0.5使用以下代码填写PDF文档的表单字段: 我得到这个错误:U+0434('AFII10069')在此字体Times-Roman(泛型:TimesNewRomanPSMT)编码:StandardEncoding with Difference中不可用 我必须在文本字段中指定哪种字体来处理西里尔(或亚洲)字符? 谢谢,罗波

    • 我有一个数据结构,其中一个主题有许多问题(一对多),一个问题有许多答案(一对多)。 我已经在主题表单中设置了问题作为嵌入式集合,由于有了烹饪书条目,我可以百分之百地解决所有问题。 当我试图开发它以在问题表单中嵌入一组答案表单时,我遇到了一个问题。 包含顶层原型表单的数据原型属性具有表单的全部深度,因此包括问题和答案的原型。但它对每个级别使用相同的占位符。 你可以在底部看到一条很长的线,我想这就是原

    • 有没有人在使用doctrine Embeddebles和symfony表单时遇到过这个问题? 如果你不知道可嵌入原则是什么,你可以在这里阅读http://doctrine-orm.readthedocs.org/en/latest/tutorials/embeddables.html 在表单提交时(在持久化到DB的过程中)将value对象(在我的情况下是CategoryType)与symfony表

    • 所以我有下面的问题。我收到一个文件,其中包含一组字体。这些字体没有嵌入到文件中。下面是一个简单的例子: 我希望将这些字体嵌入到中,这样它们就可以自包含并且始终可用。但事情似乎没那么简单。我正在使用进行处理。 我已经阅读并尝试了以下问题/答案: null