我正在尝试在代码中嵌入非常规子集。但我不断得到:
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对其进行了转换