10

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:

alt text alt text

The same text for which only the color has been changed from 0xFFFFFFFF to 0xBFFFFFFF:

alt text alt text

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; }
        }
    }
Lawrence Dol
  • 63,018
  • 25
  • 139
  • 189
  • Have you tried rendering antialiased text into a `BufferedImage` then using an `AlphaComposite` to draw the image translucently onto the screen? (It will be slower, unfortunately.) – finnw Dec 22 '10 at 19:50
  • @finnw: All painting is done to an offscreen BufferedImage, and that image is copied to the underlying screen graphics context on each `paint(Graphics agc)` using a simple `gc.drawImage`. I expect the image in the offscreen buffer to be the final image; I do lot's of translucent painting, and the only issue is that text rendering seems to be standard AA when the text color is translucent. – Lawrence Dol Dec 22 '10 at 20:29
  • Looks like this has been an issue for a while http://forums.java.net/node/676951 – Mark Bolusmjak Jan 11 '11 at 16:11

3 Answers3

1

It seems rendering text to a transparant background is not (fully) supported, as can be seen from these bugreports:

Lawrence Dol
  • 63,018
  • 25
  • 139
  • 189
Bas Leijdekkers
  • 23,709
  • 4
  • 70
  • 68
0

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

Ross
  • 1,013
  • 14
  • 32
  • No, I am using sub-pixel AA; GASP is only a fallback just in case the desktop rendering hints are not returned. This is demonstrated by the screen-shots - the *only* difference between the two is the color used for rendering. – Lawrence Dol Dec 28 '10 at 05:29
0

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:

  1. Vote on the bug report at Sun´s BugParade, to increase its priority, and wait until the Sun/Oracle programmers get to it or
  2. 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!

  • It's certainly not fixed as of 6.23; I am running the latest JVM and JDK. I do note that this talks about the destination being non-opaque, and I am using translucent source, but I suspect that the problem is when any alpha blending at all occurs. – Lawrence Dol Jan 16 '11 at 05:36
  • And doing the translucency myself is out of the question since the background over which the test is being rendered varies - it's often an image, logo or gradient - there is no one color that will work for all the pixels. – Lawrence Dol Jan 16 '11 at 05:39