当前位置: 首页 > 知识库问答 >
问题:

iText 7 Html2Pdf多次使用同一字体

岳硕
2023-03-14

我使用iText 7和Html2Pdf将表格单元格内的Html元素转换为PDF。
对于包含Html字符串的每个单元格,我使用以下代码:

ConverterProperties converterProperties = new ConverterProperties();
converterProperties.setOutlineHandler(new OutlineHandler());
converterProperties.setFontProvider(document.getFontProvider());

List<IElement> convertToElements = HtmlConverter.convertToElements(cellValue, converterProperties);
Paragraph p = (Paragraph)convertToElements.get(0);
cell.add(p);

该文件还包含其他数据,但只有此代码添加了字体的副本。(此处链接到示例)。在上面的示例中,我添加了1

编辑:
这是我为文档设置字体的方式:常规字体-

pdfFont = PdfFontFactory.createFont(fontPath, PdfEncodings.IDENTITY_H, true);
document.setFont(pdfFont);

粗体-(代码来自getBoldFont方法

FontProvider fontProvider = document.getFontProvider();

PdfFont createFont = null;
if (fontProvider == null) {
   fontProvider = new FontProvider();
   document.setFontProvider(fontProvider);
}
Collection<FontInfo> collection = fontProvider.getFontSet().get(boldFontName);
if (collection.isEmpty()) {
    createFont = PdfFontFactory.createFont(boldFontPath, PdfEncodings.IDENTITY_H, true);
    fontProvider.addFont(createFont.getFontProgram());

    // I need to call this part again because iText creates the font again
    // and in this way I eliminate another duplication of the font.
    collection = fontProvider.getFontSet().get(boldFontName);
    createFont = fontProvider.getPdfFont(collection.iterator().next());
    return createFont;
} else {
    return fontProvider.getPdfFont(collection.iterator().next());
}

至于如何“将结果元素添加到文档”,我使用document#addcanvas#showTextAligned

我的问题是,当我需要将Html转换为PDF时,如果我一直使用相同的字体(我在需要时使用getBoldFont),为什么我会多次使用粗体字体,以及如何解决这个问题。

先谢谢你。


共有1个答案

叶裕
2023-03-14

在您的用例中,iText确实创建了相同字体的多个实例,这些实例最终会出现在您的结果文档中。这种冗余是其他用例安全的副产品,例如,当调用HtmlConverter.convertToElements的结果添加到多个文档时。然而,克服这个问题非常容易。

pdfHTML将字体提供程序设置为其结果元素的属性之一。您可以直接设置字体提供程序,覆盖该属性值。因此,缓存将不再重置。可以使用以下代码将字体提供程序设置为元素:

p.setProperty(Property.FONT_PROVIDER, fontProvider);

此外,在这种情况下,您不必将任何转换器属性传递给HtmlConverter。只需使用该字体提供程序在结果元素上设置它。以下是演示如何消除字体重复的最小代码片段:

FontProvider fontProvider = new FontProvider("Arial");
fontProvider.addFont("C:/Windows/Fonts/arial.ttf");
fontProvider.addFont("C:/Windows/Fonts/arialbd.ttf");

Document document = new Document(pdfDocument);
document.setFontProvider(fontProvider);

for (int i = 0; i < 10; i++) {
    List<IElement> convertToElements = HtmlConverter.convertToElements(html);
    Paragraph p = (Paragraph) convertToElements.get(0);
    p.setProperty(Property.FONT_PROVIDER, fontProvider);
    document.add(p);
}
 类似资料:
  • 当我多次调用同一个函数时,每次都传递了不同的参数,我会这样做: 有没有更方便的方法做到这一点呢?

  • 问题内容: 我有这个,在设定的总数时我得到一个错误。为什么我不能多次访问CTE? 问题答案: A基本上是一次性视图。它只保留一个语句,然后自动消失。 您的选择包括: 重新定义第二次。从定义的末尾到您的之前,这就像复制粘贴一样简单。 将结果放入表格或变量中 将结果具体化为真实表并引用 稍微更改一下即可,只需从您的CTE: 。

  • 问题内容: 有没有办法告诉JUnit在继续下一个测试用例之前,用不同的数据连续运行一个特定的测试用例多次? 问题答案: 看看junit 4.4的理论:

  • 我在三个阶段阅读xml文件,在每个阶段,我对不同的元素感兴趣,基于输入参数。 使用XMLStreamReader多次读取一个xml文件的最佳方法是什么? 其中inputStream是FileInputStream实例 目前,我得到了StreamClosed异常或streamReader。当我开始第二阶段读取时,hasNext()为false。

  • 问题内容: 当尝试通过Spring使用Mockito时,通过bean声明创建Mock对象… …我多次调用Mockito。时发现一些奇怪的行为,而没有重置Mock对象,例如: 一旦在测试期间(在同一模拟上)多次调用此代码(“ Mockito.when”),测试就会失败并显示错误(BadSqlGrammerException,即使实际上是预期的异常,我也会失败- 如果我不抛出异常,则手动抛出该异常就可

  • 问题内容: 我有一个包含多个CTE的相当复杂的查询,但是其他人都从中提取了1个主要CTE,这是否会导致该主要CTE多次执行? 问题答案: 您可以这样使用CROSS JOIN: 这将防止的多次执行(有关实际执行计划,请参见属性)。 示例:如果执行此查询 使用数据库,那么实际的执行计划将是