首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用PDFBox嵌入fonts表单的字体

用PDFBox嵌入fonts表单的字体
EN

Stack Overflow用户
提问于 2018-12-29 09:29:53
回答 2查看 2.5K关注 0票数 1

我用PDFBox填写了一份PDF表格,在保存它之前我把它压平了。该窗体具有文本的自定义字体以及窗体字段。当我在没有安装此自定义字体的设备上打开输出文档(带有扁平字段)时,普通文本的字体仍然正确,但扁平字段的字体显示为回退(?)字体。在已经安装了这种自定义字体的设备上,一切看起来都像预期的那样。

是否有一种方法,强制使用相同的自定义字体后,对所有文本扁平窗体?

用于用PDFBox填写PDF表单的代码(简化):

代码语言:javascript
复制
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();
    }
}

PDF:输入 输出

预期:

未在系统上安装字体时的结果:

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-01-02 13:47:48

对你的PDF的一些观察(前面提到的编码问题没有-只是代表我的无知):

  1. SansDroid字体没有嵌入到PDF中。这是通过用新嵌入的F2字体替换F5字体来解决的。
  2. 设置了NeedAppearances标志,这意味着表单字段没有出现。任何读者都必须(重新)创建这些。这不是由PDFBox自动完成的,所以我添加了这个部分。
  3. 为了不引起更多关于缺少字体的警告,我完全删除了F2字体。
  4. 我在飞行前运行原始PDF,它给了我以下警告:“必需的键/Subtype丢失了。路径:->Pages->Kids>Annots->>AP->N”键确实存在,但是它似乎表明表单字段的外观出现了错误。如果我删除了/N,错误就消失了。流是"/Tx BMC EMC“--也许有一些EOL缺失了?但是,由于外观无论如何都是再生的,所以错误会在事后消失。

下面的代码将DroidSans字体嵌入到PDF中:

代码语言:javascript
复制
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 的字体只适用于提供的在其他情况下它不会。

票数 5
EN

Stack Overflow用户

发布于 2020-08-12 09:05:43

PDFont font = PDType0Font.load(document, fontFile, false);

我认为最后一个参数('false')嵌入了字体中的所有字符。当使用像日本字体这样的大字体时,会产生一个很大的pdf。所以,我尝试了下面的代码,它对我有效。

(* Scala,PDFBox 2.0.20)

代码语言:javascript
复制
// val font = PDType0Font.load(document, fontFile, true);
// form.flatten()

// hack for embed minimul font?
val page = new PDPage(PDRectangle.A6) // any page size.
val stream = new PDPageContentStream(document, page)
stream.beginText()
stream.setFont(font, 0)
stream.showText(allChars) // `allChars` are inputed all characters in forms in the creating pdf.
stream.endText()
stream.close()
// NOTE: I did NOT add the page to the PDF but worked.  

// Save the document ~
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53968324

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档