如何继承系统的抗锯齿设置,以便像 swing 那样将文本绘制到屏幕外图像?

发布于 2024-08-15 13:43:58 字数 3493 浏览 1 评论 0原文

当我在 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));
    }

When I run my swing GUI applications under Java 6, they automatically use my configured sub-pixel anti-alias settings for all fonts. The result is much improved over standard AA options.

But when I paint to an image I can find no way to initialize the graphics context to use the system's AA configuration. Trying to play around with Java's different AA hints is a lost cause because no sub-pixel method will work for all users.

Is there any way to inherit system AA settings for a given graphics context instead of having to pick one and explicitly set the hint? At the moment I have to use GASP AA to avoid the horrible results that standard AA gives with small fonts. I have tried not setting anything for text AA, and not setting any AA hints at all.


Update 2010-01-05

I think I have pinned this down; the subpixel AA hints appear to only be respected when painting directly to the AWT graphics context; when I paint to a double-buffer image it just does standard AA; but when I bypass the double-buffer image the subpixel AA is done.

Otherwise The_Fire's answer would work in JVMs which have Swing available (but not J2ME JVMs); Note that The_Fire's answer does not work using an AWT component (using new Label() instead of new JLabel() fails), presumably because the FontRenderContext cannot be extracted until the component is realized to the display.


My current code to get the graphics context for my target image currently looks like this:

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;
    }

The code to create the image uses an underlying AWT component, which forms the backdrop on which I do all my painting - the component is a Panel, because I need to be able to do a setFocusCycleRoot so it plays well with other AWT components. The create image code follows:

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));
    }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

池予 2024-08-22 13:43:58

我发现这里有几个因素。

首先,图像需要从底层 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 的问题终于得到了解决(Oracle 的做法……Sun 晚了几年十年)。

I found there were a few factors going on here.

First, the image needs to be created from the underlying AWT component, and it must be created without transparency:

cfg.createCompatibleImage(wid,hgt);

instead of

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

Second, for some inexplicable reason, the primary AA setting, KEY_ANTIALIASING, must be off to use LCD subpixel AA.

Lastly, and most importantly, the desktop font rendering hints are easily retrieved using:

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

Update 2010-01-05

Retesting in Java 6.26, it seems like the problem with needing to set general AA off to render text AA has finally been resolved (way to go Oracle... after Sun was just a few years decade too late).

人生百味 2024-08-22 13:43:58

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

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

在我的系统上,这会返回 RenderingHits.VALUE_TEXT_ANTIALIAS_LCD_HRGB。

Using Swing, I'm able to get the right text anti-aliasing hint like this:

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

On my system this returns RenderingHits.VALUE_TEXT_ANTIALIAS_LCD_HRGB.

轻许诺言 2024-08-22 13:43:58

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

java.awt.Toolkit.getDesktopProperty("awt.font.desktophints") appears to be null on linux, at least without any special vm command line options, presumably because it's unable to figure out what the platform defaults are.. adding e.g "-Dawt.useSystemAAFontSettings=lcd" seems to cure it and enables subpixel rendering if you set the hints on your Graphics2D instance.

故人爱我别走 2024-08-22 13:43:58

等等,您是在 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 领域。希望有帮助。

Wait, are you running this code on a Windows JVM? I thought ClearType was a Microsoft technology that Swing inherits through some native code (ie, not available on Linux or other non Microsoft platforms).

I once wrote a servlet that generated JPGs with anti aliased fonts that ran on Debian, and this was the code I used

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);

Offhand I can't recall if any of this code relies on Swing (I imported javax.swing and the servlet is about 300 lines long, so I may have thought I needed it for something else), a quick check on Google looks like this is squarely in the AWT space. Hope that helps.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文