【问题标题】:How to ignore missing glyphs in font used by PDFBox 2.0.7如何忽略 PDFBox 2.0.7 使用的字体中缺少的字形
【发布时间】:2018-03-08 10:48:23
【问题描述】:

当调用 PDFPageContentStream 的 showText(String) 方法时,我看到“java.lang.IllegalArgumentException: No glyph for U+05D0 in font”(例如)抛出异常。

捕捉异常并不是很有帮助,因为不会写出好的字符。也不检查输入字符串中的每个字符,这将是性能杀手(每个 PDF 可能是数千页,数百万个字符)。我真正需要的是一种方法来防止任何丢失的字形出现异常,并自动将其替换为其他字形,或者显示 unicode 值的动态创建的字形。

我不想停止生成 PDF,因为字体不支持特定字形,我只想使用一些替换字符来代替并继续。

如何做到这一点?

【问题讨论】:

  • “捕获异常并不是很有帮助,因为不会写入好的字符。也不会检查输入字符串中的每个字符,这将是性能杀手” - 如果您很少遇到该异常,您可以组合这些方法:捕获异常,并在 catch 块中检查输入字符串字符,进行相应替换,然后再次绘制(现在修改的)字符串。
  • 已经说过,如果您以良好的方式编写检查输入字符串中的每个字符,它不会成为性能杀手。
  • “我只想要一些替换字符” 所以这将导致名字中包含不寻常字符的人(例如 Miško Hevery)收到他们的名字类似于“Mi? ko Hevery”。我怀疑你的客户可能想要那个。
  • mkl,感谢您的建议。不幸的是,这仍然不够好。是否可以指定字体的层次结构?这样,我可以使用客户选择的拉丁/扩展拉丁字体和第二种已知字体作为丢失字形的后备。可能吗?
  • 我的解决方案是强制使用包含必要字形的字体。然而,这是一个糟糕的解决方案。我将不得不向 PDFBox 项目提交功能请求,要求它们支持使用主要字体的字体链,除非缺少字形,然后在字体链中为丢失的字形选择替代字体;如果没有字体包含字形,则在文档中呈现替代字形(可能包含 unicode 值)。在这种情况下抛出异常并不能促进高质量应用程序的开发。

标签: java pdf exception fonts pdfbox


【解决方案1】:

这就是我所做的

private final char[] replacements = IntStream.range(0, 1<<16)
    .map(c -> canRender(font, c) ? c : "?")
    .collect(StringBuilder::new, StringBuilder::appendCodePoint,
             StringBuilder::append)
    .toString().toCharArray();

// This is extremely ugly!!!
private boolean canRender(PDType0Font font, int codepoint) {
    try {
        font.getStringWidth(new String(Character.toChars(codepoint)));
        return true;
    } catch (final Exception e) {
        return false;
    }
}

String sanitize(String input) {
    return input.codePoints()
            .map(c -> c<replacements.length ? replacements[c] : '?')
            .collect(StringBuilder::new, StringBuilder::appendCodePoint,
                     StringBuilder::append)
            .toString();

我认为不值得优化,因为在 PDF 生成期间,还有更多工作要做,包括 hasGlyph 测试。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-11-19
    • 2014-12-24
    • 2014-12-11
    • 2017-01-11
    • 1970-01-01
    • 1970-01-01
    • 2010-09-30
    • 1970-01-01
    相关资源
    最近更新 更多