如果缺少 PDF 字体,为什么 jasper 报告不抛出 JRFontNotFoundException?

Why doesn't jasper report throw a JRFontNotFoundException if font for PDF is missing?

我读了

如果机器上没有安装字体,我预计 Jasper Reports 会抛出 JRFontNotFoundException

但是我的应用程序没有抛出 JRFontNotFoundException,尽管我没有在任何(Jaspersoft Studios、JasperReports、Adobe Acrobat Reader)机器上安装使用过的字体 "Helvetica"。

JRXML:

<parameter name="timestamp" class="java.util.Date"/>
[...]
<textField>
    <reportElement x="0" y="0" width="50" height="16" uuid="0007846a-26f1-457a-a198-67a2f7c8417c">
        <property name="local_mesure_unitwidth" value="pixel"/>
        <property name="com.jaspersoft.studio.unit.width" value="px"/>
        <property name="local_mesure_unitx" value="pixel"/>
        <property name="com.jaspersoft.studio.unit.x" value="px"/>
        <property name="local_mesure_unity" value="pixel"/>
        <property name="com.jaspersoft.studio.unit.y" value="px"/>
        <property name="local_mesure_unitheight" value="pixel"/>
        <property name="com.jaspersoft.studio.unit.height" value="px"/>
    </reportElement>
    <box padding="2"/>
    <textElement textAlignment="Left" verticalAlignment="Top">
        <font size="8" pdfFontName="Helvetica" pdfEncoding="Cp1250" isPdfEmbedded="true"/>
    </textElement>
    <textFieldExpression><![CDATA[DATEFORMAT($P{timestamp},"dd.MM HH:mm")]]></textFieldExpression>
</textField>

Maven 依赖项:

<dependency>
    <groupId>net.sf.jasperreports</groupId>
    <artifactId>jasperreports</artifactId>
    <version>5.6.0</version>
</dependency>
<dependency>
    <groupId>net.sf.jasperreports</groupId>
    <artifactId>jasperreports-functions</artifactId>
    <version>5.6.0</version>
</dependency>

Java:

private byte[] createPdf() {

    try {
        InputStream is = getClass().getResourceAsStream("MyReport.jasper");
        JasperReport jasperReport = (JasperReport) JRLoader.loadObject(is);
        Map<String, Object> parameters = new HashMap<String, Object>();
        parameters.put("timestamp", new Date());
        JRDataSource jrDataSource = new JRBeanCollectionDataSource(new Vector(), false);
        JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, parameters, jrDataSource);
        byte[] pdf = JasperExportManager.exportReportToPdf(jasperPrint);
        return pdf;
    } catch (JRException e) {
        throw new RuntimeException("Could not create PDF.", e);
    }
}

原因是 JRFontNotFoundException 仅在未安装属性 fontName 中的字体时抛出:

Exception raised when a font name used as value for the fontName attribute in the report template, is not found in any of the runtime available JasperReports font extensions, nor among the font names available to the Java Virtual Machine.

如果未安装属性 pdfFontName 中的字体(而不是使用任何其他已安装的字体),是否有任何方法可以中止生成 PDF?

您正在设置 pdfFontName 而不是 fontName

pdfFontName 是一种旧方法,现在 弃用 来指示 itext 库应该使用什么字体,jasper-reports 不会抛出 JRFontNotFoundException 如果缺少字体,itext 将抛出一个异常,该异常被捕获并作为 JRRuntimeException.

重新启动

在 itext 中,Helvetica 作为 afm 文件包含在内,因此如果使用它,itext 将不会抛出任何异常,但是这 不能保证 您的文本是 正确呈现 如果您在 jasper-reports 中指示另一种字体(在您的情况下不指示 = 默认字体)。事实上,这是一团糟, pdfFontNamepfdEncoding 都被弃用了。

如果未安装属性 pdfFontName 中的字体,是否有任何方法可以中止生成 PDF?

不要使用pdfFontName,但如果你坚持(为了问题)那么也设置fontName="Helvetica",设置jasper-如果未找到,报告字体将引发 JRFontNotFoundException

正确的方法是只设置fontName然后提供font-extensions,在字体扩展中包含实际的 ttf,指明编码以及是否应嵌入。

顺便说一句:我会使用 Identity-H 编码,推荐用于较新的 PDF 标准,并使您能够混合不同的编码。