Как использовать iText для получения PDF с несколькими шрифтами - PullRequest
0 голосов
/ 15 октября 2019

Я использую 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);
  }
}

и pndring rendring code

  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 шрифт). Я хочу получить pdf с китайскими иероглифами, используя STSong-Light, и английские символы, используя некоторые шрифты, которые изначально поддерживал iText, такие как Times-Roman.

Я обнаружил, что SO thread делает создание документавозможно с несколькими шрифтами, используя FontSelector. Но как сделать его совместимым с процессом создания PDF? XMLWorkerHelper.getInstance().parseXHtml API принимает только FontProvider в качестве параметра. Есть идеи по этому поводу?

1 Ответ

0 голосов
/ 15 октября 2019

Решение заключается в том, чтобы что-то сделать с настроенным поставщиком шрифтов, чтобы он не возвращал только один шрифт, а возвращаемый шрифт зависит от атрибута html cell 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);
  }

}

С указанным выше поставщиком шрифтов иустановите атрибут style="font-family:STSong-Light html-ячейки, содержащей китайские символы для их форматирования, а другие английские символы будут хорошо отформатированы с помощью TIMES_ROMAN;

...