1

我正在构建一个应用程序,其中允许用户使用图层将文本插入 PDF 中。

可以使用应用程序设置 PDF 页面中文本的位置,该应用程序使用JPanel 内的ICEPdf呈现 PDF 。选择图层的位置和大小后,应用程序使用iText (v. 5.3.2)将其呈现为 PDF 。

我面临的问题是 Swing 的字体渲染与 PDF 中的最终结果明显不同。

以下是一些屏幕截图,都在同一个边界框内使用 Helvetica 纯字体:

使用 Swing 渲染文本:

protected void paintComponent(Graphics g){
      //for each line...
      g.drawString(text, b0, b1);
      //b0 and b1 are computed from the selected bounding box for the text
}

我有这个:

摇摆渲染

使用 iText 渲染文本:

PdfTemplate t; //PdfTemplate is created elsewhere
ColumnText ct = new ColumnText(t);
ct.setRunDirection(PdfWriter.RUN_DIRECTION_NO_BIDI);
ct.setSpaceCharRatio(1);
ct.setSimpleColumn(new Phrase(text, font), b0, b1, b3, b4, font.getSize(), Element.ALIGN_BOTTOM); 
//b0, b1, b2 and b3 are the bounding box of the text
ct.go();

我有这个:

PDF 渲染

那么问题来了:怎样才能让 Swing 和 iText 以完全相同的方式渲染字体呢?我可以调整 Swing 或 iText,因此无论修改什么代码,我都需要为用户提供真正的所见即所得体验。

我尝试了其他字体和类型,但它们之间仍然存在一些差异。我想我缺少一些配置。

谢谢。

4

2 回答 2

2

编辑:

Java 中的字体以像素为单位,而 iText 以点为单位,我们知道每英寸有 72 个点,而对于标准的 Windows 机器,每英寸有 96 个像素/dpi。

首先我们需要找到一个点和一个像素之间的区别:

difference = 72 / dpi
      0.75 = 72 / 96

接下来我们可以将Java字体大小与差值相乘得到iText字体大小,如果java字体大小为16,那么与96dpi一起使用时iText字体大小应为12。

iTextFontSize = difference x javaFontSize
           12 = 0.75 x 16

在 Windows 机器上 96dpi 通常是标准,但请记住,并非总是如此,您应该为每台不同的机器计算它。


原帖

我相信差异是由渲染提示引起的。

解决方案1:

最好的方法是在缓冲图像上绘制所有内容。然后缓冲图像被绘制到摆动组件,并且完全相同的缓冲图像也被绘制到 PDF,这样它们之间应该没有区别。

替代想法:

另一个可能效果不佳但与现有代码配合得更好的想法是将 swing 组件的内容直接绘制到缓冲图像,然后将缓冲图像绘制到 PDF。

以下是一个快速示例,它将使用一些不同的呈现提示将 JPanel 的内容绘制到缓冲图像。(更改提示以适合您的挥杆组件)

public BufferedImage createImage(JPanel panel)
{
    BufferedImage swingComponent = new BufferedImage(
            panel.getHeight(), panel.getWidth(), 
            BufferedImage.TYPE_INT_RGB);

    Graphics2D g = swingComponent.createGraphics();

    g.setRenderingHint(RenderingHints.KEY_RENDERING,
                       RenderingHints.VALUE_RENDER_QUALITY);

    g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                       RenderingHints.VALUE_ANTIALIAS_ON);

    g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
                       RenderingHints.VALUE_INTERPOLATION_BILINEAR);

    g.dispose();
    return swingComponent; //print this to your PDF
}
于 2012-08-28T22:34:37.760 回答
0

那么问题来了:怎样才能让 Swing 和 iText 以完全相同的方式渲染字体呢?

完全一样吗?很少。假设您为两者提供相同的字体特征,渲染中可能仍然存在差异。

PDF 文件(或者实际上是文本短语)包含字体信息——系列、大小、样式等——但将文本呈现到设备的是您的 PDF 阅读器。根据您使用的程序,它可以使用平台的渲染器,也可以选择自己的一个。

AFAIK,Java Swing 使用自己的字体渲染引擎,与底层平台的渲染器不同。这使得它在跨平台看起来更加一致,但也使得文本不太可能以与任何其他程序相同的方式呈现。

知道这一点,您的选择是有限的:

  • 使用同样使用 Swing 字体渲染的 PDF 阅读器。这是一个相当有限的解决方案。

  • 使用您平台的渲染引擎绘制到 Swing。这听起来像是一个不确定的工作,也像是 SWT 可以解决的问题。也许你可以嵌入一个 SWT 组件?

于 2014-10-18T20:23:11.497 回答