首页 文章

Swing和iText字体渲染之间的差异

提问于
浏览
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
}

我有这个:

Swing rendering

使用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 rendering

所以问题是:可以做些什么来使Swing和iText以完全相同的方式呈现字体?我可以调整Swing或iText,所以无论修改什么代码,我都需要为用户提供真正的WYSIWYG体验 .

我试过其他字体和类型,但它们之间仍然存在一些差异 . 我想我错过了一些配置 .

谢谢 .

2 回答

  • 2

    编辑:

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

    首先,我们需要找到一个点和一个像素之间的差异:

    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:

    最好的方法是在缓冲图像上绘制所有内容 . 然后将缓冲的图像绘制到swing组件中,并将完全相同的缓冲图像绘制到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
    }
    
  • 0

    所以问题是:如何使Swing和iText以完全相同的方式呈现字体?

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

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

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

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

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

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

相关问题