Can Java render translucent text using sub-pixel AA?

对着背影说爱祢 提交于 2019-12-20 19:48:06

问题


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:

  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!



来源:https://stackoverflow.com/questions/4513030/can-java-render-translucent-text-using-sub-pixel-aa

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!