为什么文本在Linux中用PDF截断?

时间:2016-08-22 16:24:35

标签: java fonts jasper-reports pdf-generation export-to-pdf

我尝试在Jasper Reports中格式化Date,它适用于Windows,但不适用于Linux。使用Linux时,生成的文本将被截断。

代码:

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>

爪哇:

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);
    }
}

结果:

Windows的结果:

Windows

Linux的结果:

Linux

PDF属性:

两个生成的PDF文件在Acrobat Reader for Windows中具有相同的字体属性:

PDF properties

如您所见,字体未嵌入。 (第二种字体&#34; Helvetica&#34;如果我添加依赖项jasperreports-fonts并删除属性pdfFontNamepdfEncodingisPdfEmbedded,则会消失。

研究:

我看了:

并且解决方案似乎是嵌入字体,但它不起作用。

我使用字体&#34; Helvetica&#34;这是默认字体之一,原因如下,请参阅Wikipedia

  

这些字体或具有相同指标的合适替代字体必须始终在所有PDF阅读器中提供,因此无需嵌入PDF

https://stackoverflow.com/a/27345103/5277820

  

如果您在iText中使用这些字体,iText将忽略嵌入参数,因为可以安全地假设Adobe Reader和其他查看者可以正确渲染这些字体。

问题:

为什么Windows和Linux的字体宽度相同?或者为什么文本截断和/或换行不同?

2 个答案:

答案 0 :(得分:3)

要正确计算字体指标,需要将该字体用于java虚拟机。

请参阅此历史问题:Font is not available to the JVM with Jasper Reports,显示已启动的旧错误的各种解决方案

然而,使用jasper-reports的正确解决方案是使用字体扩展

如果您使用分布式jasperreports-font.jar,则它包含以下字体:

  DejaVu Sans
DejaVu Serif
DejaVu Sans Mono

你需要在字体名称示例fontName="DejaVu Sans"中使用其中一种,没有自动映射到其他字体,jar物理上只包含这些.ttf而没有其他(打开jar并验证不同版本的jasper-reports)。

因此,只有安装在PC上或包含在font-extension中的字体才可用于JVM。

如果您需要其他字体,最佳解决方案是生成您自己的字体扩展名,包括有效的.ttf字体,这可以在IDE中完成。

答案 1 :(得分:0)

永远不要假设客户端系统上有特定的字体 - 市面上只有几种桌面操作系统,几种西方语言版本,以及众所周知的字体列表已经过去了。稳定了几十年。

现在,创建新字体,用户以自己的语言访问内容(使用特定语言字体)变得更加容易,行业每隔几年推出一次新的外形(使用新的虚荣字体),Unicode.org发布新规范(这需要对现有字体进行检修),因此不同系统上的实际字体差异很大。

OSX和Windows在旧的“固定字体列表”模式下仍然有些功能,但新进入者没有。

对于PDF,这意味着您必须在文档中嵌入字体。 对于网络而言,这意味着灵活的网站设计不依赖于精确的像素字母尺寸。

尝试使用像Helvetica或Arial这样的旧遗留字体是一个病态案例:客户端根本不会安装它,并且会将其别名为具有不同字形指标的内容,或者它将具有古老版本,因为ASCII不受欢迎而缺少所有添加的代码点,并且无法呈现现代国际文本。由于长窗占主导地位,Arial更有可能工作,但这种情况正在迅速消失。