在pdfbox中

时间:2019-01-24 16:46:20

标签: java pdfbox opentype

我正在尝试在代码中嵌入非常规子集。但我不断得到:

java.lang.UnsupportedOperationException: OTF fonts do not have a glyf table

    at org.apache.fontbox.ttf.OpenTypeFont.getGlyph(OpenTypeFont.java:66)
    at org.apache.fontbox.ttf.TTFSubsetter.addCompoundReferences(TTFSubsetter.java:481)
    at org.apache.fontbox.ttf.TTFSubsetter.getGIDMap(TTFSubsetter.java:136)
    at org.apache.pdfbox.pdmodel.font.TrueTypeEmbedder.subset(TrueTypeEmbedder.java:306)
    at org.apache.pdfbox.pdmodel.font.PDType0Font.subset(PDType0Font.java:162)
    at org.apache.pdfbox.pdmodel.PDDocument.save(PDDocument.java:1138)

我从https://www.google.com/get/noto/help/cjk/下载了字体文件NotoSansCJK-Regular.ttc

字体子集适用于.ttf字体,因为如果保存的文档不包含特殊字符,则我没有任何问题。

编辑

看来,真正的类型集合字体可以具有shared glyf table(这是有意义的,因为字体集合包含日语字形)。因此,不能将.ttc解析的单个PDType0Font视为单个字体。

我使用以下字体加载了字体:

            ttc.processAllFonts((TrueTypeFont ttf) -> {
                PDFont font = PDType0Font.load(doc, ttf, true);
                fontList.add(font);
            });

我猜想我需要做一些额外的工作,但是我找不到任何代码示例。

EDIT2

似乎是问题所在,当子集特定的OpenType字体文件时(字体集合包含该字体文件)打开了内部标志isPostScript。然后在调用getGlyph()时检查该标志并中止过程。

以下代码在创建pdf文档时生成glyf表错误

        // downloaded from Noto project site
        String OTF_FILE = "./src/test/resources/NotoSansJP-Regular.otf";
        PDDocument doc = new PDDocument();
        PDFont otf = null;
        try (InputStream inputStream = new FileInputStream(new File(OTF_FILE))) {
            otf = PDType0Font.load(doc, new OTFParser().parse(inputStream), true);
            PDPage page = new PDPage();
            PDPageContentStream stream = new PDPageContentStream(doc, page);
            stream.setFont(otf, 10f);
            stream.beginText();
            stream.newLineAtOffset(100f, 600f);
            stream.showText("二ろほス反2化みた大第リきやね景手ハニエ者性ルヤリウ円脱");
            stream.endText();
            stream.close();
            doc.addPage(page);
            doc.save("test.pdf");
        } catch (IOException iox) {
            // failed
        }

,但是只要在PDType0Font.load调用中将subsetting参数设置为true,它将立即生成pdf格式

如果我通过集合加载otf字体,则很简单:

        String OTF_FILE = "./src/test/resources/NotoSansCJK-Regular.ttc";
        PDDocument doc = new PDDocument();
        PDFont otf = null;
        try (InputStream inputStream = new FileInputStream(new File(OTF_FILE))) {
            TrueTypeCollection ttc = new TrueTypeCollection(inputStream);
            otf = PDType0Font.load(doc, ttc.getFontByName("NotoSansCJKjp-Regular"), true);
            PDPage page = new PDPage();
            PDPageContentStream stream = new PDPageContentStream(doc, page);
            stream.setFont(otf, 10f);
            stream.beginText();
            stream.newLineAtOffset(100f, 600f);
            stream.showText("二ろほス反2化みた大第リきやね景手ハニエ者性ルヤリウ円脱");
            stream.endText();
            stream.close();
            doc.addPage(page);
            doc.save("test.pdf");
        } catch (IOException iox) {
            // failed
        }

我需要嵌入整个字体,否则子集将引发错误

编辑3 我最终通过从“特定于语言的OpenType / CFF(OTF)”中下载OTF字体来规避此问题,该字体包含所有4个区域的字符,并使用fonttools中的otf2ttf对其进行了转换

0 个答案:

没有答案