我發現雖然渲染Java中的不透明文本(最新版本6u23)使用子像素AA就好,但渲染半透明文本不會。Java可以使用亞像素AA渲染半透明文字嗎?
子像素AA:
用於僅僅顏色已經從0xFFFFFFFF的改變0xBFFFFFFF同樣的文字:
正如你所看到的,半透明的文字顯然是標準的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; }
}
}
您是否嘗試將抗鋸齒文本渲染到`BufferedImage`中,然後使用`AlphaComposite`將圖像半透明地繪製到屏幕上? (不幸的是,它會變慢) – finnw 2010-12-22 19:50:01
@finnw:所有的繪畫都是在屏幕外的BufferedImage上完成的,並且使用一個簡單的`gc.drawImage`將該圖像複製到每個`paint(Graphics agc)`的底層屏幕圖形上下文中。我希望屏幕外緩衝區中的圖像是最終圖像;我做了很多半透明的繪畫,唯一的問題是當文本顏色是半透明的時候,文本渲染似乎是標準AA。 – 2010-12-22 20:29:15
看起來這是一段時間的問題http://forums.java.net/node/676951 – z5h 2011-01-11 16:11:05