了解 PDFBox 2.0 中字体的加载
Understanding loading of font in PDFBox 2.0
我终于成功地让 PDFBox 打印了我的 unicode。
但是现在,我想了解我提出的解决方案。
下面的代码有效并在页面上打印 ≥
。
有两件事不起作用:
改变
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 之前的许多其他问题中已经涵盖了这个问题,其中在处理 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 通常是最好的。
我终于成功地让 PDFBox 打印了我的 unicode。
但是现在,我想了解我提出的解决方案。
下面的代码有效并在页面上打印 ≥
。
有两件事不起作用:
改变
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 之前的许多其他问题中已经涵盖了这个问题,其中在处理 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 通常是最好的。