ONJava.com -- The Independent Source for Enterprise Java
oreilly.comSafari Books Online.Conferences.


AddThis Social Bookmark Button

Java Internationalization and Localization
Pages: 1, 2, 3, 4, 5

Detecting the Java version and vendor

By detecting the Java version and vendor, we ensure that our code will always work. We will not encounter unnecessary exceptions when we obtain Class objects for either GraphicsEnvironment or FontX class.

We can obtain the Java version and vendor as follows:

String vendor = System.getProperty("java.vendor");
String version = System.getProperty("java.version");

The following table shows the vendor values and versions on different browsers.

  Netscape Navigator 4.76 Netscape Navigator 6 IE
Vendor Netscape Communications Corporation Sun Microsystems Inc. Microsoft Corp.
Version 1.1.5 1.3.0_01 1.1.4

Java Reflection

With Java reflection, we ensure that we are able to compile our NEFontFactory class using any version of the Java compiler, since we do not need to import any Java version specific code. For more information on Java Reflection, check out Sun's Java Tutorial.

Retrieving Class Objects

The first step is to retrieve the Class object. With the knowledge of Java version and vendor, we obtain our FontX and GraphicsEnvironment Class objects with the following method calls for IE VM and JDK 1.3, respectively.

Class msFontX = Class.forName("com.ms.awt.FontX"); // Class object for IE environment
Class graphicEnv = Class.forName("java.awt.GraphicsEnvironment"); // JDK 1.3 environment

Invoking Methods

Next, we will look at invoking methods. In the MS SDK Java doc, we find the following documentation.

FontX Class
The FontX Class of the com.ms.awt package creates a font object that defines the font family, font face, style, and size. The FontX class also supports TrueType fonts.

public class FontX extends FxFont
// Fields
public static final int EMBEDDED;
public static final int OUTLINE;
public static final int STRIKEOUT;
public static final int UNDERLINE;

// Constructors
public FontX();
public FontX(String name, int style, int size);
public FontX(String name, int style, int size, boolean bEmbed);
public FontX(String name, int style, int size, int xFlags);

// Methods
public boolean equals(Object obj);
public static String[] getAttributeList();
public static String[] getAttributeList(String face);
public int getFlags();
public static int getFlagsVal(String face, String attribute);
public static Font getFont(String face, int style, int size, int flags);
public static Font getFont(String face, Vector v, int size);
public static String[] getFontList();
public static int getStyleVal(String face, String attribute);
public boolean isTypeable(int language);
public static boolean matchFace(String face);
public String toString();

With JDK 1.1, fonts are mapped with a font properties file. So, we can obtain different fonts by editing this file. However, the Microsoft implementation does not support this type of font association. Therefore, we can obtain desired fonts with FontX objects, which are created with Win32 font names.

FontX field definitions

Indicates the new font should be linked to a privately embedded font. Note This is only significant for fonts that are loaded by non-Java objects. Fonts that are loaded by Java objects are automatically embedded.


Indicates that the text drawn by using the new font should be drawn by using the outline of the glyph. This is only supported by certain fonts in the system, and only GraphicsX will support this feature. Trying to draw outline fonts using a Win32Graphics object will result in the glyph being drawn normally.


Indicates that text drawn using the new font should be struck through.


Indicates that text drawn using the new font should be underlined.

We are interested in getFont(String face, int style, int size, int flags) and getFontList() in FontX.

We get the available font listing and Font object from the FontX class using reflection.

Getting a font listing:

Method getFontListApi = msFontX.getMethod("getFontList", null);
// need to perform sorting of the listing .... (see Exercise)
String fontListing[] = (String[])getFontListApi.invoke(null, null);

Creating a Font:

String fname = new String(fontName);

Class[] param = new Class[4];
param[0] = fname.getClass();
param[1] = Integer.TYPE;
param[2] = Integer.TYPE;
param[3] = Integer.TYPE;

Method getFontApi = msFontX.getMethod("getFont", param);

Field field = msFontX.getField("EMBEDDED");

Integer fstyle = new Integer( style );
Integer fsize = new Integer( size );
Integer fflags = (Integer)field.get( null ); // null because it is a static field.

Object[] args = { fname, fstyle, fsize, fflags};
Font f = ( Font ) getFontApi.invoke(null, args ); // null because it is a static method.

For Sun Java VM (1.1 and above), the Font object is created normally,

new Font(fontName, style, size);

while the font listing is obtained via Java Reflection for Java 1.3:

Method getLocalGraphicsEnvironmentApi =
graphicEnv.getMethod("getLocalGraphicsEnvironment", null);
// invoke the API to obtain an instance of GraphicsEnvironment
Object GEInstance =
getLocalGraphicsEnvironmentApi.invoke(null, null); // static method with no parameters
Method getAvailableFontFamilyNamesApi =
String fontListing [] =
(String[])getAvailableFontFamilyNamesApi.invoke(GEInstance, null);

Font caching

We know that object creation takes up a fair bit of time, and so font caching is added to the NEFontFactory class to improve the performance of Font object creation.

Caching is implemented using java.util.Hashtable, where the key is formed using fontName+style+size.

We place a Font object into Hashtable by the following (where f is the Font object):

String name = f.getName();
int style = f.getStyle();
int size = f.getSize();
cache.put( name+style+size, f);

Putting in all together

Now we can obtain a Font object by calling

public static Font NEFontFactory.getFont(Sting fontName, int style, int size)

And for a listing of font names available on your system, we can call

public static String[] NEFontFactory.getFontList()

Pages: 1, 2, 3, 4, 5

Next Pagearrow