2010-12-22 86 views
10

我發現雖然渲染Java中的不透明文本(最新版本6u23)使用子像素AA就好,但渲染半透明文本不會。Java可以使用亞像素AA渲染半透明文字嗎?

子像素AA:

alt textalt text

用於僅僅顏色已經從0xFFFFFFFF的改變0xBFFFFFFF同樣的文字:

alt textalt text

正如你所看到的,半透明的文字顯然是標準的AA,而不是一個乾淨的半透明渲染,它具有可怕的'90年代'蜘蛛俠'外觀。

這是由於一般的子像素AA的技術限制,或在Java中的一個bug,或者只是因爲Java甚至沒有嘗試爲半透明的文字,或有我錯過了什麼?


顯卡初始化

dbGraphics=(Graphics2D)dbImage.getGraphics(); 
if(dctRoot.properties.getBoolean("Antialias",true)) { 
    try { 
     Map hnts=(Map)(dctRoot.awtComponent.getToolkit().getDesktopProperty("awt.font.desktophints")); 

     // SET AA ON OVERALL (NOTE: GENERAL AA MUST BE OFF FOR SUBPIXEL AA TO BE HONORED - TEXT WIDGETS MUST DO THIS THEMSELVES) 
     dbGraphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON); 

     if(hnts!=null) { 
      // SET FONT RENDERING HINTS FROM DESKTOP 
      dbGraphics.addRenderingHints(hnts); 
      } 
     else { 
      try { 
       // SET TEXT AA TO FONT-SPECIFIED GASP AA (JAVA 6+) 
       dbGraphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,RenderingHints.class.getField("VALUE_TEXT_ANTIALIAS_GASP").get(null)); 
       } 
      catch(Throwable thr3) { 
       // SET TEXT AA TO DEFAULT 
       dbGraphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,RenderingHints.VALUE_TEXT_ANTIALIAS_ON); 
       } 
      } 
     } 
    catch(Throwable thr) { 
     dctRoot.log.println("Antialiasing not supported on this JVM ("+thr+")."); 
     dctRoot.setProperty("Antialias","False");   // turn off AA for subsequent painting 
     } 
    } 
else { 
    try { 
     dbGraphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_OFF); 
     dbGraphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,RenderingHints.VALUE_TEXT_ANTIALIAS_OFF); 
     } 
    catch(Throwable thr) {;}        // ignore exception 
    } 

文本渲染

Object oaa=disableGeneralAA(gc); 
... 
gc.drawString(tl,xx,(ty+(xa*met.getHeight()))); 
restoreGeneralAA(gc,oaa); 

... 


static private volatile boolean   hasRenderingHints=true; 

// ***************************************************************************** 
// STATIC INIT & MAIN 
// ***************************************************************************** 

// ***************************************************************************** 
// STATIC METHODS 
// ***************************************************************************** 

/** 
* Disable the general anti-aliasing rendering hint, returning whether the old value was RenderingHints.VALUE_ANTIALIAS_ON. 
* <p> 
* This method is needed for text rendering due to a bug in AWT; as of Java 6_20 when general AA is on text is not rendered using subpixel 
* AA, so general AA has to be turned off before rendering text and turned back on when done. This method abstracts that work and deals 
* with the possibility that the JVM does not support rendering hints, such as is the case with JME JVMs. 
*/ 
static public Object disableGeneralAA(Graphics2D gc) { 
    Object        old=null; 

    if(hasRenderingHints) { 
     try { 
      old=gc.getRenderingHint(RenderingHints.KEY_ANTIALIASING); 
      gc.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_OFF); 
      } 
     catch(NoClassDefFoundError thr) { hasRenderingHints=false; } 
     catch(NoSuchFieldError  thr) { hasRenderingHints=false; } 
     catch(NoSuchMethodError thr) { hasRenderingHints=false; } 
     } 
    return old; 
    } 

/** 
* Disable the general anti-aliasing rendering hint, returning whether the old value was RenderingHints.VALUE_ANTIALIAS_ON. 
* <p> 
* This method is needed for text rendering due to a bug in AWT; as of Java 6_20 when general AA is on text is not rendered using subpixel 
* AA, so general AA has to be turned off before rendering text and turned back on when done. This method abstracts that work and deals 
* with the possibility that the JVM does not support rendering hints, such as is the case with JME JVMs. 
*/ 
static public void restoreGeneralAA(Graphics2D gc, Object val) { 
    Object        old=null; 

    if(hasRenderingHints && val!=null) { 
     try { gc.setRenderingHint(RenderingHints.KEY_ANTIALIASING,val); } 
     catch(NoClassDefFoundError thr) { hasRenderingHints=false; } 
     catch(NoSuchFieldError  thr) { hasRenderingHints=false; } 
     catch(NoSuchMethodError thr) { hasRenderingHints=false; } 
     } 
    } 
+0

您是否嘗試將抗鋸齒文本渲染到`BufferedImage`中,然後使用`AlphaComposite`將圖像半透明地繪製到屏幕上? (不幸的是,它會變慢) – finnw 2010-12-22 19:50:01

+0

@finnw:所有的繪畫都是在屏幕外的BufferedImage上完成的,並且使用一個簡單的`gc.drawImage`將該圖像複製到每個`paint(Graphics agc)`的底層屏幕圖形上下文中。我希望屏幕外緩衝區中的圖像是最終圖像;我做了很多半透明的繪畫,唯一的問題是當文本顏色是半透明的時候,文本渲染似乎是標準AA。 – 2010-12-22 20:29:15

+0

看起來這是一段時間的問題http://forums.java.net/node/676951 – z5h 2011-01-11 16:11:05

回答

0

我認爲它是因爲你使用GASP從字體樣式取分。您是否嘗試過使用VALUE_TEXT_ANTIALIAS_DEFAULT和VALUE_ALPHA_INTERPOLATION_DEFAULT?這是值得一試的。

http://download.oracle.com/javase/6/docs/api/java/awt/RenderingHints.html

+0

不,我使用的是亞像素AA;只有在桌面渲染提示未被返回的情況下,GASP纔是後備。屏幕截圖顯示了這一點 - 兩者之間的唯一區別就是用於渲染的顏色。 – 2010-12-28 05:29:08

0

什麼Jav你使用的是哪一個版本?你不會說。但很顯然,這已被固定爲任的Java 6 Update 12時(J6u12)或JDK7 B43

在這裏看到: http://bugs.sun.com/view_bug.do?bug_id=6749060

如果您使用Java再次測試=或高於J6u12,仍然可以看到該bug,有是一個RFE,您可以在Sun的錯誤數據庫中進行評論。

得到的東西固定在Java平臺的方式,是兩種:

  1. 表決關於在Sun的BugParade bug報告,以提高其優先級,並等待,直到太陽/ Oracle的程序員們到它 或
  2. 現在Java是開源的,自己修復它。 (加入ho的郵件列表。IO/jkp5 :-)

要投票或發表評論的Bugparade報告是在這裏(如果你有一個j6u12 it's仍然存在測試)是 網址:ho.io/jkp2

如果你想實現一個已知的變通使文本即使在較老的JRE一個變通這裏提供看起來不錯

網址:ho.io/jkpy

「看起來,我要作的解決方案通過將所需的前景色與組分的背景色混合來模擬半透明度t仍然是確保使用本地光柵化器的方法。「

祝你好運!