2012-08-28 63 views
1

我正在構建一個應用程序,該應用程序允許用戶使用圖層將文本插入到PDF中。Swing和iText字體呈現之間的差異

可以使用應用程序設置PDF頁面中文本的位置,該應用程序在JPanel內使用ICEPdf呈現PDF。選擇圖層的位置和大小後,應用程序使用iText(v。5.3.2)將其呈現爲PDF。

我面臨的問題是,來自Swing的字體渲染與PDF中的最終結果略有不同。

下面是一些屏幕截圖,都使用相同的邊框內的黑體Plain字體:

渲染與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體驗。

我嘗試過使用其他字體和類型,但它們之間仍然存在一些差異。我想我錯過了一些配置。

謝謝。

+0

你使用哪種字體?您可以嘗試在PDF中嵌入字體。你也可以檢查字符對的字距,並在任何一邊進行定製。 – StanislavL

+0

我在兩側都使用了Helvetica平原。 Helvetica是核心字體之一,所以我不認爲我必須導入它。克寧可能是其中一個問題。你有什麼想法在Swing中如何改變它? –

+0

你在使用itext的fontmapper嗎?你在嵌入字體嗎? – djeikyb

回答

2

編輯:

字體在Java中以像素爲單位,但iText的措施點,我們知道有72點每英寸,而對於標準的Windows機器有每英寸/ dpi的96個像素。

首先,我們需要找到一個點和像素之間的區別:

difference = 72/dpi 
     0.75 = 72/96 

接下來,我們可以用差來獲得iText的字體尺寸乘以Java的字體大小,如果Java字體大小爲16 ,那麼當使用96dpi時,iText字體大小應該是12。

iTextFontSize = difference x javaFontSize 
      12 = 0.75 x 16 

在Windows機器上96DPI往往是常態,但請記住,並非總是如此,你應該把它解決每個不同的機器。


原貼

我相信差異是由呈現提示所致。

解決方案1:

做到這一點是制定一個緩衝圖像上的一切的最好方式。然後緩衝的圖像被繪製到擺動組件,並且完全相同的緩衝圖像也被繪製到PDF上,這樣它們之間應該沒有區別。

備用理念:

另一種想法,可能無法正常工作爲好,但會與您現有的代碼更好地工作是Swing組件的內容繪製直接到緩衝圖像,然後緩衝圖像繪製到PDF 。

以下是一個快速示例,它將使用幾個不同的呈現提示將JPanel的內容繪製到緩衝圖像。 (更改提示,滿足您的Swing組件)

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 
} 
+1

儘管此解決方案可以工作,但最終結果可能很差。渲染文本(而不是圖像)時,文本可以在渲染時與PDF的其餘部分完美匹配。如果我使用圖片,用戶縮放文檔時,圖片可能會變成[pixelated](http://en.wikipedia.org/wiki/Pixelation)(主要是文本)。爲了緩解這個問題,我不得不使用更大的圖像(更多的dpi),這將增加PDF的大小。 –

+0

嘿,萬一你錯過了它:我已經編輯了我的帖子一個更好的解決方案。 – sorifiend

+0

我不知道這是否是問題...通過任何值減小iTextFontSize只是使差異比以前更大。 –

0

所以,問題是:什麼可以做,使Swing和iText的渲染字體完全相同的方式?

正好一樣嗎?很少。假定您爲兩者提供相同的字體特徵,渲染中可能仍會存在差異。

PDF文件(或者真的是文本短語)包含字體信息 - 系列,大小,樣式等 - 但是它是將PDF文件呈現給設備的PDF閱讀器。根據您使用的程序,它可以使用平臺的渲染器,也可以選擇其中一種。

AFAIK,Java Swing使用自己的字體渲染引擎,與底層平臺的渲染器截然不同。這使得它在各個平臺上看起來更加一致,但也使得文本不會像其他程序那樣呈現出來。

知道的是,你的選擇是有限的:

  • 使用也使用Swing字體渲染PDF閱讀器。這是一個相當有限的解決方案。

  • 使用您的平臺的渲染引擎繪製Swing。這聽起來像是工作,也像SWT會解決的。也許你可以嵌入一個SWT組件?

相關問題