代码之家  ›  专栏  ›  技术社区  ›  Little Helper

了解PDFBox 2.0中字体的加载

  •  7
  • Little Helper  · 技术社区  · 8 年前

    我终于成功地让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之前的许多其他问题中得到了解决,在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 回复  |  直到 5 年前
        1
  •  3
  •   Tilman Hausherr    8 年前

    如评论中所述:

    • 通过使用2.0.7版本,EmbedSubset的问题得以解决。(Btw 2.0.8今天发布);
    • 问题“U+2265在此字体的编码中不可用:WinAnsiencecoding”在 FAQ 解决方法是使用 PDType0Font.load() 你已经在你的工作版本中做到了;
    • 字体没有UTF-8编码,因为它在PDF规范中不可用;
    • 使用embedSubsets true生成4KB的文件,如果使用false,则文件为100KB,因为嵌入了完整字体,因此false通常是最好的。