Anti-Aliased Text Without Code





Anti-Aliased Text Without Code

Draw anti-aliased text without any code changes at all using two clever tricks introduced in Java 5.0.

Since Java 1.2, UI programmers can draw anti-aliased text. Unfortunately, anti-aliasing must be enabled for every Swing component by writing a few lines of code for each of them [Hack #53]. This hack describes a clever way to turn on anti-aliasing for an entire frame by adding a customized repaint manager. As every programmer seeks for effortless solutions, we will discover how to do the same without writing any lines of code.

The Java 5.0 Trick

Sun Microsystems released Java 5.0, a.k.a. Tiger, in September 2004. Among many improvements, like a new theme for the Metal L&F, this release of J2SE paves the way for application-wide text anti-aliasing support in Mustang, the upcoming release of Java. To this end, the Swing team added a special field in the hidden class com.sun.java.swing.SwingUtilities2. Meant for internal purposes only, this class is left undocumented by Sun's engineering teams.

If you look closely at its source code, provided in src.zip with Sun's JVM, you'll discover a very interesting method: drawTextAntialiased(JComponent c). This method returns a boolean value used by Swing's painting framework to know whether the specified component must be drawn with anti-aliased text. Here is its complete source code:

	private static boolean drawTextAntialiased(JComponent c) {
		if (!AA_TEXT_DEFINED) {
			if (c != null) {
				return ((Boolean)c.getClientProperty(
				           AA_TEXT_PROPERTY_KEY)).booleanValue();
			}
			return false;
		}
		return AA_TEXT;
	}

As you can see, there are two ways to enable anti-aliased text. In the first case, the static variable AA_TEXT_DEFINED is set to false, and a check is performed against the component's properties. Hence, a component in which the property AA_TEXT_PROPERTY_KEY is set to true will be anti-aliased. You can set this property to a given component with the following line of code:

	myComponent.putClientProperty(SwingUtilities2.AA_TEXT_PROPERTY_KEY,
		new Boolean(true));

Add this line of code in any of your applications, compile it, and launch it with J2SE 5.0 and you'll see the magic happen. While extremely useful, this trick is not enough since we sure don't want to do that for every component instance in our UI. The source code of drawTextAntialiased() gives us a clue to understand how to globally enable anti-aliased text. When AA_TEXT_ DEFINED is set to true, the value AA_TEXT is returned. Both are defined at the beginning of SwingUtilities2.java:

	static {
		fontCache = new LSBCacheEntry[CACHE_SIZE];
		Object aa = java.security.AccessController.doPrivileged(
			new GetPropertyAction("swing.aatext"));	
		AA_TEXT_DEFINED = (aa != null);
		AA_TEXT = "true".equals(aa);
		AA_FRC = new FontRenderContext(null, true, false);
	}

The variables we are interested in are computed according to the value of the object aa. This object is the value of a JVM property called swing.aatext, and it is supposed to be a String object. AA_TEXT_PROPERTY_KEY is true only when this property has been set, and AA_TEXT is true when the value of the property is the String value "true". Given this information, we just need to set the swing.aatext property of the JVM to enable anti-aliasing. This can be done on the command line with the help of the D switch, as in this example:

javaDswing.aatext=true WebHunter

Figure is what an application looks like with swing.aatext properly set. I have also shown a screenshot of the same application without this property for comparison (in Figure).

Anti-aliased text with J2SE 5.0 swing.aatext property


This trick is very useful and extremely simple to set up. Best of all, it requires no change in the source code of the application, allowing use of it even with applications you did not write. Unfortunately, this hack has two major drawbacks. First, it works only with Sun's J2SE 5.0 and is not guaranteed to be available with other vendors' implementations. Also, remember that SwingUtilities2 is an undocumented and hidden class for which no support will ever be provided. This means that it can be changed without notice. Using it might break your applications in a future release of Java.

Anti-aliased text without J2SE 5.0 swing.aatext property


Romain Guy


     Python   SQL   Java   php   Perl 
     game development   web development   internet   *nix   graphics   hardware 
     telecommunications   C++ 
     Flash   Active Directory   Windows