了解 PDFBox 2.0 中字体的加载

Understanding loading of font in PDFBox 2.0

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

有两件事不起作用:

第一个更改打印两个点而不是字符。 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;
    }
}

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

如评论中所述:

  • embedSubsets 的问题在使用版本 2.0.7 后消失了。 (顺便说一句,今天发布了 2.0.8);
  • 问题 "U+2265 is not available in this font's encoding: WinAnsiEncoding" 在 FAQ 中进行了解释,解决方案是使用您已经在工作版本中使用的 PDType0Font.load()
  • 字体没有 UTF-8 编码,因为它在 PDF 规范中不可用;
  • 使用 embedSubsets true 生成一个 4KB 的文件,false 文件为 100KB,因为嵌入了完整的字体,所以 false 通常是最好的。