11

当我在 Java 6 下运行我的 swing GUI 应用程序时,它们会自动使用我为所有字体配置的亚像素抗锯齿设置。结果比标准 AA 选项有很大改进。

但是当我绘制图像时,我找不到初始化图形上下文以使用系统的 AA 配置的方法。尝试使用 Java 的不同 AA 提示是一个失败的原因,因为没有亚像素方法适用于所有用户。

有没有办法为给定的图形上下文继承系统 AA 设置,而不必选择一个并显式设置提示?目前我必须使用 GASP AA 来避免标准 AA 用小字体给出的可怕结果。我尝试不为文本 AA 设置任何内容,也没有设置任何 AA 提示。


2010-01-05 更新

我想我已经确定了这一点;亚像素 AA 提示似乎只有在直接绘制到 AWT 图形上下文时才会受到尊重;当我绘制双缓冲图像时,它只是执行标准 AA;但是当我绕过双缓冲图像时,子像素 AA 就完成了。

否则 The_Fire 的答案将适用于有 Swing 可用的 JVM(但不是 J2ME JVM);请注意,The_Fire 的答案在使用 AWT 组件时不起作用(使用 new Label() 而不是 new JLabel() 失败),大概是因为在组件实现显示之前无法提取 FontRenderContext。


我当前获取目标图像的图形上下文的代码如下所示:

try {
    if((dbImage=dctRoot.createImage(wid,hgt,1))!=null) {            // if createImage returns null or throws an exception the component is not yet displayable
        dbGraphics=(Graphics2D)dbImage.getGraphics();
        if(dctRoot.properties.getBoolean("Antialias",true)) {
            try {
                // set AA on overall
                dbGraphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING     ,RenderingHints.VALUE_ANTIALIAS_ON);
                // set text AA to platform/impl default
                dbGraphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,RenderingHints.VALUE_TEXT_ANTIALIAS_DEFAULT);
                // try to override platform/impl AA with font-specified AA (Java 6+)
                try { dbGraphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,RenderingHints.class.getField("VALUE_TEXT_ANTIALIAS_GASP").get(null)); } catch(Throwable thr) {;} // yes, ignore exception
                }
            catch(Throwable thr) {
                dctRoot.log.println("Antialiasing not supported on this JVM ("+thr+").");
                dctRoot.setProperty("Antialias","False");           // turn off AA for subsequent painting
                }
            }
        }
    }
catch(Throwable thr) {
    dbImage=null;
    dbGraphics=null;
    }

创建图像的代码使用了一个底层 AWT 组件,它构成了我在其上进行所有绘画的背景 - 该组件是一个面板,因为我需要能够执行 setFocusCycleRoot 以便它与其他 AWT 组件很好地配合。创建图像代码如下:

public DctImage createImage(int wid, int hgt, float accpty) {
    GraphicsConfiguration               cfg=awtComponent.getGraphicsConfiguration();
    Image                               img=null;

    if(transparentImages) {
        //y { img=new BufferedImage(wid,hgt,BufferedImage.TYPE_INT_ARGB); }     // NB: J2ME CDC/PP 1.1 does not have the BufferedImage constructors (one day I may discover a way to create a BufferedImage via another API!!)
        try { img=cfg.createCompatibleImage(wid,hgt,Transparency.TRANSLUCENT); }// NB: J2ME CDC/PP 1.1 does not have this API, but prefer to use GraphicsConfiguration over new BufferImage(...)
        catch(NoClassDefFoundError   thr) { transparentImages=false; createImage(wid,hgt,accpty); } // try again with transparency disabled
        catch(NoSuchMethodError      thr) { transparentImages=false; createImage(wid,hgt,accpty); } // try again with transparency disabled
        catch(NoSuchFieldError       thr) { transparentImages=false; createImage(wid,hgt,accpty); } // try again with transparency disabled
        }
    else {
        img=cfg.createCompatibleImage(wid,hgt);
        }

    if(accpty>0 && SET_ACCELERATION_PRIORITY!=null) {
        try { SET_ACCELERATION_PRIORITY.invoke(img,new Object[]{new Float(accpty)}); } catch(Throwable thr) {;}
        }

    return (img==null ? null : new DctImage(img));
    }
4

4 回答 4

7

我发现这里有几个因素。

首先,图像需要从底层 AWT 组件创建,并且必须创建不透明:

cfg.createCompatibleImage(wid,hgt);

代替

cfg.createCompatibleImage(wid,hgt,Transparency.TRANSLUCENT);

其次,由于某些莫名其妙的原因,主 AA 设置 KEY_ANTIALIASING 必须关闭才能使用 LCD 子像素 AA。

最后,也是最重要的一点,桌面字体渲染提示很容易使用:

java.awt.Toolkit.getDesktopProperty("awt.font.desktophints")

2010-01-05 更新

在 Java 6.26 中重新测试,似乎需要设置通用 AA 以呈现文本 AA 的问题终于得到了解决(去甲骨文的路……在 Sun晚了几年之后)。

于 2010-01-09T07:15:47.697 回答
6

使用 Swing,我可以获得正确的文本抗锯齿提示,如下所示:

JLabel label = new JLabel();
FontMetrics fm  = label.getFontMetrics( label.getFont() );
Object aaHintValue = fm.getFontRenderContext().getAntiAliasingHint();

在我的系统上返回RenderingHits.VALUE_TEXT_ANTIALIAS_LCD_HRGB

于 2009-12-22T19:27:10.670 回答
2

java.awt.Toolkit.getDesktopProperty("awt.font.desktophints") 在 linux 上似乎为空,至少没有任何特殊的 vm 命令行选项,大概是因为它无法弄清楚平台默认值是什么.. 添加例如“ -Dawt.useSystemAAFontSettings=lcd" 如果您在 Graphics2D 实例上设置提示,似乎可以治愈它并启用子像素渲染。

于 2012-03-28T14:18:00.457 回答
1

等等,你是在 Windows JVM 上运行这段代码吗?我认为 ClearType 是 Swing 通过一些本机代码继承的 Microsoft 技术(即,在 Linux 或其他非 Microsoft 平台上不可用)。

我曾经写过一个 servlet,它使用在 Debian 上运行的抗锯齿字体生成 JPG,这就是我使用的代码

Font font = new Font("Komix", Font.PLAIN, 8);
Graphics2D g2;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
FontRenderContext  frc = g2.getFontRenderContext();
g2.setFont(font);
g2.setPaint(Color.black);
g2.drawString(sMessage, xOffset, yOffset);

临时我不记得是否有任何代码依赖于 Swing(我导入了 javax.swing 并且 servlet 大约有 300 行长,所以我可能认为我需要它来做其他事情),在 Google 上的快速检查看起来像这样正好在 AWT 空间中。希望有帮助。

于 2009-12-23T19:39:26.727 回答