问题
I have found that while rendering opaque text in Java (latest version 6u23) uses sub-pixel AA just fine, rendering translucent text does not.
Sub-pixel AA:
The same text for which only the color has been changed from 0xFFFFFFFF to 0xBFFFFFFF:
As you can see, the translucent text is clearly standard AA and rather than a clean translucent rendering, it has that awful '90s "spidery" appearance.
Is this due to a technical limitation for sub-pixel AA in general, or a bug in Java, or just because Java doesn't even try for translucent text, or have I missed something?
Graphics Initialization
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
}
Text Rendering
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; }
}
}
回答1:
It seems rendering text to a transparant background is not (fully) supported, as can be seen from these bugreports:
- http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6728834
- http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6749060
- http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6749069
回答2:
I think its because your using GASP which takes the points from the font style. have you tried using VALUE_TEXT_ANTIALIAS_DEFAULT and VALUE_ALPHA_INTERPOLATION_DEFAULT? it's worth a shot.
http://download.oracle.com/javase/6/docs/api/java/awt/RenderingHints.html
回答3:
What Java version are you using? You don´t say. But apparently this has been fixed as of either Java 6 update 12 (J6u12) or JDK7 b43
See here: http://bugs.sun.com/view_bug.do?bug_id=6749060
If your test again with Java = or higher than J6u12 and still see the bug, there´s an RFE where you can comment on at Sun´s bug database.
The way to get things fixed in the Java platform, is to either:
- Vote on the bug report at Sun´s BugParade, to increase its priority, and wait until the Sun/Oracle programmers get to it or
- Now that Java is open source, fix it yourself. (join the mailing list at ho.io/jkp5 :-)
The Bugparade report you want to vote or comment in is here (in case you test with j6u12 an it´s still present) is url: ho.io/jkp2
If you want to implement a known work-around so the text looks nice even in older JREs a work-around is provided here
url: ho.io/jkpy
"Looks like the solution that i'm using to emulate the translucency by mixing the required foreground color with the background color of the component is still the way to go to make sure that the native rasterizer is used."
Good luck!
来源:https://stackoverflow.com/questions/4513030/can-java-render-translucent-text-using-sub-pixel-aa