为什么 PDF 中的文本被截断为 Linux?
Why is text truncated in PDF with Linux?
我尝试在 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>
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);
}
}
结果:
Windows的结果:
Linux的结果:
PDF 属性:
对于 Windows:
,两个生成的 PDF 文件在 Acrobat Reader 中具有相同的字体属性
如您所见,字体未嵌入。 (如果我添加依赖项 jasperreports-fonts
并删除属性 pdfFontName
、pdfEncoding
和 isPdfEmbedded
,第二个字体 "Helvetica" 就会消失)。
研究:
我阅读了:
- PDF generated with jasperreport not showing well on Linux but yes on Mac, could the os be related?
- http://community.jaspersoft.com/questions/527138/pdf-text-truncated-linux-fine-windows
- http://community.jaspersoft.com/questions/803503/why-text-filed-value-will-be-truncated-if-application-running-linux
解决方案似乎是嵌入字体,但它不起作用。
我使用字体 "Helvetica",这是默认字体之一,这就是原因,请参阅 Wikipedia:
These fonts, or suitable substitute fonts with the same metrics, must always be available in all PDF readers and so need not be embedded in a PDF
和:
If you use these fonts in iText, iText will ignore the embedded parameter, because it is safe to assume that Adobe Reader and other viewers can render these fonts correctly.
问题:
为什么Windows和Linux相同的字体宽度不同?或者为什么文本截断 and/or 换行不同?
要正确计算字体指标,字体需要可用于 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.
中完成
永远不要假设特定字体在客户端系统上可用 - 市场上只有几个桌面操作系统的日子已经一去不复返了,提供少数西方语言,以及众所周知的字体列表几十年来一直稳定。
现在创建新字体要容易得多,用户可以使用自己的语言访问内容(使用特定语言的字体),行业每隔几年就会推出新的外形规格(使用新的个性化字体),Unicode.org发布新规范(需要彻底修改现有字体),因此不同系统上的实际字体差异很大。
OSX 和 Windows 仍然在旧的 "fixed font list" 模式下有些功能,但新进入者不会。
对于 PDF,这意味着您必须在文档中嵌入字体。
对于网络,这意味着灵活的网站设计不依赖于精确的像素字母尺寸。
尝试使用像 Helvetica 或 Arial 这样的旧旧字体是一种病态的情况:要么客户根本不会安装它,并将其别名为具有不同字形规格的东西,要么它有一个古老的版本,缺少自 ASCII 失宠以来添加的所有代码点,并且将无法呈现现代国际文本。由于 windows 的长期优势,Arial 更有可能发挥作用,但这种优势正在迅速消失。
我尝试在 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>
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);
}
}
结果:
Windows的结果:
Linux的结果:
PDF 属性:
对于 Windows:
,两个生成的 PDF 文件在 Acrobat Reader 中具有相同的字体属性如您所见,字体未嵌入。 (如果我添加依赖项 jasperreports-fonts
并删除属性 pdfFontName
、pdfEncoding
和 isPdfEmbedded
,第二个字体 "Helvetica" 就会消失)。
研究:
我阅读了:
- PDF generated with jasperreport not showing well on Linux but yes on Mac, could the os be related?
- http://community.jaspersoft.com/questions/527138/pdf-text-truncated-linux-fine-windows
- http://community.jaspersoft.com/questions/803503/why-text-filed-value-will-be-truncated-if-application-running-linux
解决方案似乎是嵌入字体,但它不起作用。
我使用字体 "Helvetica",这是默认字体之一,这就是原因,请参阅 Wikipedia:
These fonts, or suitable substitute fonts with the same metrics, must always be available in all PDF readers and so need not be embedded in a PDF
和:
If you use these fonts in iText, iText will ignore the embedded parameter, because it is safe to assume that Adobe Reader and other viewers can render these fonts correctly.
问题:
为什么Windows和Linux相同的字体宽度不同?或者为什么文本截断 and/or 换行不同?
要正确计算字体指标,字体需要可用于 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.
永远不要假设特定字体在客户端系统上可用 - 市场上只有几个桌面操作系统的日子已经一去不复返了,提供少数西方语言,以及众所周知的字体列表几十年来一直稳定。
现在创建新字体要容易得多,用户可以使用自己的语言访问内容(使用特定语言的字体),行业每隔几年就会推出新的外形规格(使用新的个性化字体),Unicode.org发布新规范(需要彻底修改现有字体),因此不同系统上的实际字体差异很大。
OSX 和 Windows 仍然在旧的 "fixed font list" 模式下有些功能,但新进入者不会。
对于 PDF,这意味着您必须在文档中嵌入字体。 对于网络,这意味着灵活的网站设计不依赖于精确的像素字母尺寸。
尝试使用像 Helvetica 或 Arial 这样的旧旧字体是一种病态的情况:要么客户根本不会安装它,并将其别名为具有不同字形规格的东西,要么它有一个古老的版本,缺少自 ASCII 失宠以来添加的所有代码点,并且将无法呈现现代国际文本。由于 windows 的长期优势,Arial 更有可能发挥作用,但这种优势正在迅速消失。