Java Internationalization and Localization
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 |
| EMBEDDED |
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. |
| OUTLINE |
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. |
| STRIKEOUT |
Indicates that text drawn using the new font
should be struck through. |
| UNDERLINE |
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 =
graphicEnv.getMethod("getAvailableFontFamilyNames",null);
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()