Making anti-aliasing in Java work
Today I had quite a bad (although, eventually successful) experience of trying to fix anti-aliasing in JDK. The problem is that it is not on by default (at least for those members of the fringe who use something slick like XMonad instead of monstrosities like Gnome) and to turn it on one needs to set the awt.useSystemAAFontSettings Java VM property to one of the supported values (e.g. gasp, or lcd).
Now, I'm not really keen on changing the code of every Java application I happen to run on my machine, nor can I add -Dawt.useSystemAAFontSettings=lcd to every Java command line (did they really mean it?!). I started to look for a method to set properties globally, and of course I found suggestions of using swing.properties file. In retrospect, that wasn't a smart thing to try: I wanted to set AWT property, not Swing one, so eventually (by reading JDK source code) I found out that Java wasn't loading all the properties from the file, only those few which it knew, and it was obscure about the one I needed.
Fast-forward several hours, I found out that there is another interesting file: accessibility.properties. Although JDK only sets the properties that thinks can appear in the file (which isn't very helpful), one of the properties there is really a big step towards the solution, its key is assistive_technologies. This property value is a class name which gets instantiated some time during AWT initialization. Now, if only we could create a class which sets the abominable anti-aliasing property when instantiated, it would solve the problem once and for all... Or would it?
We need one more piece of the puzzle: suppose we have the class compiled, how do we make JRE see it, so that it could load it. If JRE doesn't have it in its classpath, an AWTError would be thrown during assistive technologies initialization. Setting classpath on the command line is not going to help us: we specificially wanted to do without changing Java command lines. Setting CLASSPATH environment variable won't help either: as per java(1) man, if classpath is set on the command line, it overrides the CLASSPATH variable completely. And putting the class/jar file into JRE lib directory doesn't make it visible to the system classloader — bummer!
Good news: we have the JDK source code and if one knows what to look for, its usually not that hard to find. The thing I was looking for was the list of initial classpath elements. Actually, I could just append my anti-aliasing workaround class into rt.jar, but that's not very flexible. So I found the list, and after a list of JRE jars there was a directory: "classes/"! Since the search is done starting from the JRE home directory, I could just create the classes directory there and put my class there.
My workaround class code follows:
package hacks;
public class AntialiasingHack {
public AntialiasingHack() {
System.setProperty("awt.useSystemAAFontSettings", "lcd_hrgb");
}
}
Contents of jre/lib/accessibility.properties (or ~/.accessibility.properties) file:
assistive_technologies=hacks.AntialiasingHack
PS: If you have a more clean solution (other than filing an RFE for a generic startup properties file loader, arguing that it won't make the system more insecure than it already is, and waiting for several yearsjiffies to get it actually implemented and delivered in the next version of JDK), please-please-pretty-please tell me!