Java Swing和iText字体呈现之间的差异
我正在开发一个应用程序,其中包括允许用户使用图层将文本插入PDF 可以使用应用程序设置文本在PDF页面中的位置,该应用程序使用JPanel内部呈现PDF。选择层的位置和大小后,应用程序使用(5.3.2)将其渲染到PDF 我面临的问题是,Swing中的字体渲染与PDF中的最终结果有明显不同 以下是一些屏幕截图,它们都使用同一边界框内的Helvetica普通字体: 使用Swing呈现文本:Java Swing和iText字体呈现之间的差异,java,swing,pdf,itext,Java,Swing,Pdf,Itext,我正在开发一个应用程序,其中包括允许用户使用图层将文本插入PDF 可以使用应用程序设置文本在PDF页面中的位置,该应用程序使用JPanel内部呈现PDF。选择层的位置和大小后,应用程序使用(5.3.2)将其渲染到PDF 我面临的问题是,Swing中的字体渲染与PDF中的最终结果有明显不同 以下是一些屏幕截图,它们都使用同一边界框内的Helvetica普通字体: 使用Swing呈现文本: protected void paintComponent(Graphics g){ //for
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();
我有这个:
所以问题是:如何使Swing和iText呈现字体的方式完全相同?我可以调整Swing或iText,所以无论修改什么代码,我都需要用户真正的体验
我尝试了其他字体和类型,但它们之间仍然存在一些差异。我想我缺少一些配置
谢谢。编辑:
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的内容绘制到缓冲图像。(更改提示以适合您的swing组件) 所以问题是:如何使Swing和iText呈现字体的方式完全相同 完全一样?很少。假定您为两者提供相同的字体特征,在呈现时可能仍然会引入差异 PDF文件(或者实际上是文本短语)包含字体信息系列、大小、样式等,但将文本呈现到设备上的是PDF阅读器。根据您使用的程序,它可以使用平台的渲染器,也可以选择自己的渲染器 另外,JavaSwing使用自己的字体渲染引擎,这与底层平台的渲染器不同。这使得它在不同平台上看起来更加一致,但也使得文本不太可能以其他程序相同的方式呈现 知道这一点,您的选择是有限的:
- 使用同样使用Swing字体呈现的PDF阅读器。这是一个相当有限的解决方案
- 使用平台的渲染引擎绘制Swing。这听起来像是不确定的工作,也像SWT应该解决的问题。也许你可以嵌入一个SWT组件
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
}