Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I inherit the system's anti-alias setting for painting text to off-screen images like swing does?

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));
    }
like image 658
Lawrence Dol Avatar asked Dec 15 '09 22:12

Lawrence Dol


People also ask

How do I use anti-alias in Photoshop?

To anti-alias, you must select the Anti-Alias option before making the selection; you cannot add anti-aliasing to an existing selection. In the Edit workspace, select the Lasso, Polygonal Lasso, Magnetic Lasso, Elliptical Marquee, or Magic Wand tool. Select Anti-aliased in the options bar.

How do I turn on anti-aliasing?

Start the game and set antialiasing to "enable" or "on", or "2x" or "4x" through the game menu. Game does not support antialiasing when HDR rendering is enabled. Select Override any application setting in the NVIDIA Control Panel and select the desired antialiasing level.

How do I turn off anti-aliasing in Photoshop?

Shape layers have to have anti-aliasing. That's just how they work in PS. With the shape tool selected, check the tool options and on the left side you will see a dropdown that says Shape . Change that to Pixels and a new checkbox option ( anti-alias ) will appear.

Do you use anti-aliasing when drawing?

The “anti-aliasing” feature can be added to any drawing tool, such as pen, shape, selection, etc., to slightly blur the edge of the drawn line and make it look smoother. Now let's compare and see what changes when we use this. There are those who should use this feature and those who should turn it off.


1 Answers

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

like image 131
Lawrence Dol Avatar answered Oct 23 '22 06:10

Lawrence Dol