Wednesday, August 18, 2010

Java Text - When Platform Independence Fails

I‘ve recently been working on a Java web application that does server-side rendering of complex graphics that include text. Having sweated all the details to maximize the quality of the application’s output; having finally made the application sufficiently stable and feature-complete to enter beta testing; and having jumped through some unrelated hoops to make the production host usable, I finally found myself at the point where I could deploy the application to its production server.

I thought I was on the brink of success at long last, but when I tried the web application on its production Linux VM, the results were terrible. The text was rendered very differently between Java 1.6 on Mac OS X, which is my development environment, and Java 1.6 on Linux, which is the deployment environment. Specifically, the resolution-independent, anti-aliased, fractional-sized text was rendered beautifully by Java on Mac OS X, and horribly by Java on Linux. You can see for yourself in the examples below. (Due to confidentiality rules, I can’t show the entire rendering, which is unfortunate in this case, because the differences are even more striking when seen en masse.)


Text rendered by Java on Mac OS X, using
“Java(TM) SE Runtime Environment (build 1.6.0_20-b02-279-10M3065)”.


Text rendered by Java on Linux, using
“Java(TM) SE Runtime Environment (build 1.6.0_12-b04)”.


Above, the two samples converted to an animated GIF and perpetually alternating.

Note that in both cases, exactly the same typefaces are being used: Arial (bold and plain) in the yellow area, and Georgia (plain) for the names above. Also in both cases, the rendering was performed in a Graphics2D environment with all of its hints set to maximum quality, and the backing BufferedImage was of the same type (TYPE_INT_RGB). Both systems are even using exactly the same TrueType fonts; I copied them from my Mac to the JRE on the Linux box. Nonetheless, Java’s font rendering under Linux looks like some early, unfinished attempt at supporting TrueType, anti-aliasing and fractional font sizes/metrics. Java on Mac OS X, on the other hand, handles all of the text beautifully.

My best guess is that the results on Linux are representative of the true capabilities of Java's built-in text renderer, while the very different results on Mac OS X are probably due to Apple’s Java engineers substituting OS X’s native font renderer for Java’s. Others seem to have reached similar conclusions in the past.

So, because of these platform dependent text rendering behaviors, I’ve gone from believing that I was ready to deploy an application whose quality was going to reflect well on myself and my organization, while delighting its users, to being so ashamed of the graphics quality that I don’t want to proceed with the deployment; I don’t want to be associated with such poor quality, and I don’t want it being seen as representative of the care that my organization puts into its work.

Arguably, the platform independence was undone by Apple (if the scenario above is correct), but Java’s native text rendering is so bad, I can’t blame them. In fact, I’m glad there’s at least one platform that can run Java and render text well. The real fault seems to be with Sun’s (now Oracle’s) management for not giving Java’s text engine the attention it deserves.

Of course, if anyone knows that I’m wrong about those conclusions, and can show me how to get the same quality of text rendering out of Java on Linux as I get from Java on Mac OS X, I’d be very grateful. And so, I think, would others.

Help if you can, please. Beware of this issue, if you can’t.

4 comments:

  1. You probably no longer even CARE about this, but as a Linux user, I think I see what the problem is.

    I do not know if Java really even uses the font antialiasing configuration file on Linux, but modifying it (usually you would use the GUI, but on a server you often don't have one) could significantly improve the rasterization of your fonts.

    For the user that will be running the Java application, make a file with this name (the dot at the beginning is important):

    .fonts.conf

    And here are what I believe your preferred settings should be:






    none




    true




    hintslight




    true

    ReplyDelete
  2. Tynach,

    I still care very much, so thanks a lot for your comment/tip. Unfortunately, the Blogger comment system seems to have stripped-out important material. If you can find a way to post a follow-up comment that includes the missing material, or provides a link to it somewhere else, that'd be great.

    ----Chris

    ReplyDelete
  3. Unfortunately, it seems it may be a moot point :/ It seems Java doesn't care about what Linux says font rendering should look like, unless you tell it specifically. I see some posts about that here and there, but I'm unable to reproduce it here (using jEdit as the test program, I don't know Java programming myself). It seems people say that various Java programs that DO listen to Linux's font configuration, do some weird abstraction between Java and the UI in order to do it (such as Open Office), but those comments are old.

    A link to all the material you'd need to know about Linux font configuration is here:
    https://wiki.archlinux.org/index.php/Font_Configuration

    Various posts containing info about Java specifically are scattered, but this comes to mind:
    https://bbs.archlinux.org/viewtopic.php?id=90250

    I am in no way an Arch Linux user, but they seem to have the best documentation on this. I hope this helps!

    I think what I suggested the settings to be for you, were "no subpixel rendering, antialias on, hinting on slight." Don't remember what the last 'true' was, though.

    ReplyDelete
  4. Well, I did some more research. It turns out Java DOES use FreeType, which is Linux's native font rendering. However, it does not use FontConfig (Linux's configuration utilities for configuring FreeType) for it's font rendering. Instead, you have to program in how you want fonts to render.

    I think you said in there that you have hinting on full. You probably want hinting either off, or on slight. There are also other options (mentioned in the ArchWiki page I posted).

    http://www.sabi.co.uk/Notes/linuxFonts.html

    That link, if you scroll down (might want to search for "It does not use" to get to the right segment of text) has some information about it.

    ReplyDelete