了解 PDFBox 2.0 中字体的加载

Lit*_*per 7 pdfbox

我终于成功地让 PDFBox 打印了我的 unicodes。但是现在,我想了解我提出的解决方案。下面的代码有效并将 a 打印?到页面。

两件事不起作用:

  • 更改 PDType0Font.load(documentMock, systemResourceAsStream, true);PDType0Font.load(documentMock, systemResourceAsStream, false);

  • 更改 final PDFont robotoLight = loadFontAlternative("Roboto-Light.ttf");final PDFont robotoLight = loadFont("Roboto-Light.ttf");

第一个更改打印两个点而不是字符。 embedSubset 有什么作用,因为它在设置为 false 时不起作用? 文档太少,我无法理解。

第二个更改提供了以下异常Exception in thread "main" java.lang.IllegalArgumentException: U+2265 is not available in this font's encoding: WinAnsiEncoding 此问题已在许多其他问题中涵盖,这些问题早于 PDFBox 2.0,其中在处理 unicode 时存在错误。所以,他们不直接回答这个问题。除此之外,问题很明显:我不应该将编码设置为 WinAnsiEncoding 而是不同的东西。 但是编码应该是什么?为什么没有UTF-8编码或类似的可用? COSName 中没有关于许多选项的文档。

public class SimpleReportUnicode {
    public static void main(String[] args) throws IOException {
        PDDocument report = createReport();
        final String fileLocation = "c:/SimpleFormUnicode.pdf";
        report.save(fileLocation);
        report.close();
    }

    private static PDDocument createReport() throws IOException {
        PDDocument document = new PDDocument();
        PDPage page = new PDPage();
        document.addPage(page);

        PDPageContentStream contentStream = new PDPageContentStream(document, page);
        final PDFont robotoLight = loadFontAlternative("Roboto-Light.ttf");
        writeText(contentStream, robotoLight, 100, 650);

        contentStream.close();
        return document;
    }

    private static void writeText(PDPageContentStream contentStream, PDFont font, double x, double y) {
        try {
            contentStream.beginText();
            contentStream.setFont(font, 12);
            contentStream.moveTextPositionByAmount((float) x, (float) y);
            String unicode = "?";
            contentStream.showText(unicode);
            contentStream.endText();
        }
        catch (IOException e) {
        }
    }

    private static PDFont loadFont(String location) {
        PDFont font;
        try {
            PDDocument documentMock = new PDDocument();
            InputStream systemResourceAsStream = ClassLoader.getSystemResourceAsStream(location);
            Encoding encoding = Encoding.getInstance(COSName.WIN_ANSI_ENCODING);
            font = PDTrueTypeFont.load(documentMock, systemResourceAsStream, encoding);
        }
        catch (IOException e) {
            throw new RuntimeException("IO exception");
        }
        return font;
    }

    private static PDFont loadFontAlternative(String location) {
        PDDocument documentMock = new PDDocument();
        InputStream systemResourceAsStream = ClassLoader.getSystemResourceAsStream(location);
        PDFont font;
        try {
            font = PDType0Font.load(documentMock, systemResourceAsStream, true);
        }
        catch (IOException e) {
            throw new RuntimeException("IO exception");
        }
        return font;
    }
}
Run Code Online (Sandbox Code Playgroud)

编辑 如果您想使用与代码中相同的字体,Roboto 可在此处获得:https : //fonts.google.com/specimen/Roboto 将 Roboto-Light.ttf 添加到您的类路径中,代码应该开箱即用.

Til*_*err 3

正如评论中所讨论的:

  • 使用 2.0.7 版本后,embedSubsets 的问题就消失了。(顺便说一句,2.0.8 今天发布了);
  • 问题“U+2265 在此字体的编码中不可用:WinAnsiEncoding”在常见问题解答中进行了解释,解决方案是使用PDType0Font.load()您在工作版本中已经执行过的操作;
  • 字体没有 UTF-8 编码,因为它在 PDF 规范中不可用;
  • 使用 embedSubsets true 会生成 4KB 文件,使用 false 则文件为 100KB,因为嵌入了完整字体,因此 false 通常是最好的。