了解在PDFBox 2.0中加载字体

时间:2017-11-03 09:21:19

标签: pdfbox

我终于成功地制作了PDFBox打印我的unicodes。 但现在,我想了解我提出的解决方案。 下面的代码适用于页面打印

有两件事不起作用:

  • 改变 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之前的许多其他问题中已经涵盖了这个问题,其中存在处理unicodes的错误。 所以,他们没有直接回答这个问题。 除此之外,问题很明显:我不应该将编码设置为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添加到类路径中,代码应该开箱即用。

1 个答案:

答案 0 :(得分:2)

如评论中所述:

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