A tricky issue with java.awt.Font
If your code or code you use relies on loading fonts by name, you may face severe limitations when trying to use your application in a different environment than the one you performed your tests. Although many of us are aware of the fact specific fonts may not be installed on a machine, trying to work around this problem may prove to be more difficult as it seems at first.
Most code that loads fonts by name use either the
getFont(String name) or the
getFont(String name, Font defaultFont) method from the
java.awt.Font class. What happens when there is no font registered in the OS whose name is
name? In the first case,
null is returned; for the second method, the
defaultFont parameter is returned. This will probably lead to unexpected results. Even when the font exists in the OS, it may not be the same font you were expecting. Yes, that is right: there are different font files for "common" fonts. So, how can you load a specific font and make sure the one you expect will be used to render text?
Font API allows you to programatically load a font from a
java.io.InputStream using the
createFont(int fontFormat, InputStream fontStream) method. Although the only font format supported is
Font.TRUETYPE_FONT, this should be enough for most situations, since if you are not using a TrueType font, there is no guarantee it will render the same in different platforms and/or devices. Unfortunately, there is a problem that prevents this solution from working most of the times: there is no way to associate a loaded font with a name. This is somewhat surprising, since the loaded instance even returns the correct name when its
getName() method is called.
So, how to solve this problem? If you wrote the code or can modify its source, you simply need to rewrite the parts that load a font by name so that they delegate to a method that looks up the instance in a "registry", such as a
Map. The problem gets worse, though, when you are working with third-party software. If you can modify the binaries in runtime, using AOP to work around this problem is a possible solution. However, sometimes the third-party license prohibits this kind of modification and then there isn't much the developer can do besides asking the vendor to rewrite the API.
The long term fix for this issue would be to add a
register(String name, Font font) method to
Font in Mustang. Should I propose an enhancement about this? I would like to know what you think.