【问题标题】:Can Java render translucent text using sub-pixel AA?Java可以使用亚像素AA渲染半透明文本吗?
【发布时间】:2011-05-29 14:54:21
【问题描述】:

我发现虽然在 Java(最新版本 6u23)中渲染不透明文本使用亚像素 AA 就好了,但渲染半透明文本却没有。

亚像素 AA:

只有颜色从 0xFFFFFFFF 更改为 0xBFFFFFFF 的相同文本:

如您所见,半透明文本显然是标准 AA,而不是干净的半透明渲染,它具有 90 年代可怕的“蜘蛛”外观。

这是由于一般亚像素 AA 的技术限制,还是 Java 中的错误,或者仅仅是因为 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:所有的绘画都是在屏幕外的 BufferedImage 上完成的,并且使用简单的gc.drawImage 将该图像复制到每个paint(Graphics agc) 上的底层屏幕图形上下文中。我希望屏幕外缓冲区中的图像是最终图像;我做了很多半透明的画,唯一的问题是当文字颜色是半透明的时候,文字渲染似乎是标准的AA。
  • 看起来这个问题已经有一段时间了forums.java.net/node/676951

标签: java text-rendering


【解决方案1】:

我认为这是因为您使用 GASP 从字体样式中获取要点。您是否尝试过使用 VALUE_TEXT_ANTIALIAS_DEFAULT 和 VALUE_ALPHA_INTERPOLATION_DEFAULT?值得一试。

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

【讨论】:

  • 不,我用的是亚像素AA; GASP 只是一个备用方案,以防不返回桌面渲染提示。屏幕截图证明了这一点 - 两者之间的唯一区别是用于渲染的颜色。
【解决方案2】:

【讨论】:

  • 我将透明 text 渲染到 opaque 背景。
【解决方案3】:

您使用的是什么 Java 版本?你不说。但显然这已在 Java 6 update 12 (J6u12) 或 JDK7 b43 中得到修复

请看这里: http://bugs.sun.com/view_bug.do?bug_id=6749060

如果您再次使用 Java = 或高于 J6u12 进行测试并且仍然发现错误,那么您可以在 Sun 的错误数据库中评论 RFE。

在 Java 平台中解决问题的方法是:

  1. 在 Sun 的 BugParade 上对错误报告进行投票,以提高其优先级,并等待 Sun/Oracle 程序员处理它 或
  2. 既然 Java 是开源的,请自行修复。 (加入 ho.io/jkp5 的邮件列表 :-)

您想要投票或评论的 Bugparade 报告在这里(如果您使用 j6u12 进行测试并且它仍然存在)是 网址:ho.io/jkp2

如果您想实现一个已知的解决方法,即使在较旧的 JRE 中文本看起来也不错,这里提供了解决方法

网址:ho.io/jkpy

“看起来我用来通过将所需的前景色与组件的背景色混合来模拟半透明的解决方案仍然是确保使用本机光栅化器的方法。”

祝你好运!

【讨论】:

  • 从 6.23 开始肯定没有修复;我正在运行最新的 JVM 和 JDK。我确实注意到这谈到了目的地是不透明的,并且我使用的是半透明源,但我怀疑问题在于何时发生任何 alpha 混合。
  • 我自己做半透明是不可能的,因为渲染测试的背景会有所不同——通常是图像、徽标或渐变——没有一种颜色适用于所有像素。
猜你喜欢
  • 2014-08-07
  • 2011-02-28
  • 1970-01-01
  • 2023-03-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-13
  • 1970-01-01
相关资源
最近更新 更多