如何使用 iText 获取以多种字体呈现的 pdf
How to use iText get pdf rendered with multiple fonts
我正在使用 iText 将 html 解析为包含英文和中文字符的 pdf。我正在使用
// for pdf rendering
compile group: 'com.itextpdf', name: 'itextpdf', version: '5.5.13.1'
// for pdf rendering
compile group: 'com.itextpdf.tool', name: 'xmlworker', version: '5.5.13.1'
我已经让汉字解析成为可能而不是依赖性问题
// for chinese font in pdf rendering
compile group: 'com.itextpdf', name: 'itext-asian', version: '5.2.0'
和自定义字体提供程序
public class StSongProvider extends XMLWorkerFontProvider {
private static final Logger LOG = LoggerFactory.getLogger(StSongProvider.class);
public StSongProvider() {
super(null, null);
}
@Override
public Font getFont(final String fontName, String encoding, float size, final int style) {
BaseFont bfChinese = null;
try {
bfChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
} catch (Exception e) {
LOG.error("Not found STSong-Light,maybe com.itextpdf.itext-asian dependency problem");
}
return new Font(bfChinese, size, style);
}
}
和pdf渲染代码
public static File html2Pdf(String html, String fileName) {
try {
String path = buildPath(fileName);
// step 1
Document document = new Document(PageSize.A4);
document.setMargins(20, 20, 0, 0);
// step 2
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(path));
// step 3
document.open();
// step 4
InputStream cssInput = null;
XMLWorkerHelper.getInstance().parseXHtml(writer, document, new ByteArrayInputStream(html.getBytes(StandardCharsets.UTF_8)), cssInput, new StSongProvider());
// step 5
document.close();
LOG.info("PDF file: {} rendering successfully", path);
return new File(path);
} catch (IOException ex) {
// do something
} catch (DocumentException ex) {
// do something
}
}
但是如果没有合适的字体(所有字符都使用 STSong-Light
字体),结果 pdf 中的英文字符不是那么漂亮。我想使用 STSong-Light
使用中文字符呈现 pdf,使用 iText 最初支持的一些字体(例如 Times-Roman
.
使用英文字符呈现 pdf
我发现 SO thread 可以使用 FontSelector 构建包含多种字体的文档。但是如何让它与pdf创建过程兼容呢? XMLWorkerHelper.getInstance().parseXHtml
api 只接受一个 FontProvider
作为参数。对此有什么想法吗?
解决方案是在自定义字体提供程序上做一些事情,使它不是 return 只有一种字体,而是 return 字体取决于 html 单元格 font-family
属性.
public class StSongProvider extends XMLWorkerFontProvider {
private static final Logger LOG = LoggerFactory.getLogger(StSongProvider.class);
public StSongProvider() {
super(null, null);
}
@Override
public Font getFont(final String fontName, String encoding, float size, final int style) {
BaseFont font = null;
try {
if (StringUtils.equals(fontName, "STSong-Light")) {
font = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
} else {
font = BaseFont.createFont(FontFactory.TIMES_ROMAN, FontFactory.defaultEncoding, true);
}
} catch (Exception e) {
// do something
}
return new Font(font, size, style);
}
}
使用上述字体提供程序,并设置 html 单元格的 style="font-family:STSong-Light
属性包含中文字符以对其进行格式化,其他英文字符将被格式化为 TIMES_ROMAN
;
我正在使用 iText 将 html 解析为包含英文和中文字符的 pdf。我正在使用
// for pdf rendering
compile group: 'com.itextpdf', name: 'itextpdf', version: '5.5.13.1'
// for pdf rendering
compile group: 'com.itextpdf.tool', name: 'xmlworker', version: '5.5.13.1'
我已经让汉字解析成为可能而不是依赖性问题
// for chinese font in pdf rendering
compile group: 'com.itextpdf', name: 'itext-asian', version: '5.2.0'
和自定义字体提供程序
public class StSongProvider extends XMLWorkerFontProvider {
private static final Logger LOG = LoggerFactory.getLogger(StSongProvider.class);
public StSongProvider() {
super(null, null);
}
@Override
public Font getFont(final String fontName, String encoding, float size, final int style) {
BaseFont bfChinese = null;
try {
bfChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
} catch (Exception e) {
LOG.error("Not found STSong-Light,maybe com.itextpdf.itext-asian dependency problem");
}
return new Font(bfChinese, size, style);
}
}
和pdf渲染代码
public static File html2Pdf(String html, String fileName) {
try {
String path = buildPath(fileName);
// step 1
Document document = new Document(PageSize.A4);
document.setMargins(20, 20, 0, 0);
// step 2
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(path));
// step 3
document.open();
// step 4
InputStream cssInput = null;
XMLWorkerHelper.getInstance().parseXHtml(writer, document, new ByteArrayInputStream(html.getBytes(StandardCharsets.UTF_8)), cssInput, new StSongProvider());
// step 5
document.close();
LOG.info("PDF file: {} rendering successfully", path);
return new File(path);
} catch (IOException ex) {
// do something
} catch (DocumentException ex) {
// do something
}
}
但是如果没有合适的字体(所有字符都使用 STSong-Light
字体),结果 pdf 中的英文字符不是那么漂亮。我想使用 STSong-Light
使用中文字符呈现 pdf,使用 iText 最初支持的一些字体(例如 Times-Roman
.
我发现 SO thread 可以使用 FontSelector 构建包含多种字体的文档。但是如何让它与pdf创建过程兼容呢? XMLWorkerHelper.getInstance().parseXHtml
api 只接受一个 FontProvider
作为参数。对此有什么想法吗?
解决方案是在自定义字体提供程序上做一些事情,使它不是 return 只有一种字体,而是 return 字体取决于 html 单元格 font-family
属性.
public class StSongProvider extends XMLWorkerFontProvider {
private static final Logger LOG = LoggerFactory.getLogger(StSongProvider.class);
public StSongProvider() {
super(null, null);
}
@Override
public Font getFont(final String fontName, String encoding, float size, final int style) {
BaseFont font = null;
try {
if (StringUtils.equals(fontName, "STSong-Light")) {
font = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
} else {
font = BaseFont.createFont(FontFactory.TIMES_ROMAN, FontFactory.defaultEncoding, true);
}
} catch (Exception e) {
// do something
}
return new Font(font, size, style);
}
}
使用上述字体提供程序,并设置 html 单元格的 style="font-family:STSong-Light
属性包含中文字符以对其进行格式化,其他英文字符将被格式化为 TIMES_ROMAN
;