java - 如何使用 iText 获取使用多种字体渲染的 pdf

标签 java pdf fonts itext

我正在使用 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
    }
  }

但是如果没有合适的字体,结果pdf中的英文字符就不那么漂亮了(所有字符都使用STSong-Light字体)。我想使用 STSong-Light 渲染中文字符,使用 iText 最初支持的一些字体(例如 Times-Roman)渲染英文字符。

我找到了这个SO thread使用 FontSelector 可以构建具有多种字体的文档。但如何使其兼容 pdf 创建过程呢? XMLWorkerHelper.getInstance().parseXHtml API 仅接受 FontProvider 作为参数。对此有什么想法吗?

最佳答案

解决方案是对自定义字体提供程序做一些处理,使其不只返回一种字体,而是返回取决于 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;

关于java - 如何使用 iText 获取使用多种字体渲染的 pdf,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58397571/

相关文章:

android webview设置系统默认字体大小?

java - Spring 的Aspectj

java - 具有特殊接收符号的正则表达式和 ReplaceAll() 会引发错误

java - 获取工作日 getter

java - Joda time - 格式不同时解析

javascript - "/^\s*$/"在此 JavaScript 中意味着什么?

ios - CCMenuItemAtlasFont 用法

javascript - 如何可靠地将 HTML 转换为 PDF

java - 如何在 Java 中以编程方式减小 PDF 文件的大小?

fonts - 将 TTF 字体添加到 PhoneGap 应用程序