我们有一个可以显示中文文本的小程序。我们正在为它指定一种字体(Arial),它在 Windows 和 Mac OSX 下都能正常工作。
但在 Linux 上的 Firefox 中,汉字被渲染为正方形。有没有办法解决这个问题?请注意,我们不能假设客户端上存在特定的字体文件。
我们有一个可以显示中文文本的小程序。我们正在为它指定一种字体(Arial),它在 Windows 和 Mac OSX 下都能正常工作。
但在 Linux 上的 Firefox 中,汉字被渲染为正方形。有没有办法解决这个问题?请注意,我们不能假设客户端上存在特定的字体文件。
这表明该字体不支持中文字符(您可能已经猜到了)。
您可能会发现 java.awt.Font.canDisplayUpto() 方法很有趣。
http://www.j2ee.me/javase/6/docs/api/java/awt/Font.html#canDisplayUpTo(java.lang.String)
"指示此字体是否可以显示指定的字符串。对于使用 Unicode 编码的字符串,了解特定字体是否可以显示字符串很重要。此方法返回字符串 str 的偏移量,这是此字体不能显示的第一个字符不使用缺少的字形代码显示。如果字体可以显示所有字符,则返回 -1。
这是因为 Windows 和 Mac 上的 Arial 都是 Unicode 字体,但它在 Linux 上只有 Latin-1 字符集。在许多 Linux 发行版上,中文字体是可选的,并且可能没有中文字体可用。
一种常见的技术是搜索所有字体,看看它们中的任何一个都可以显示汉字。例如,
static final Font defaultFont =new Font( "Arial Unicode MS", Font.BOLD, 48 );
static private Font[] allFonts;
static final char sampleChineseCharacter = '\u4F60'; // ni3 as in ni3 hao3
public static void loadFonts() {
GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment();
allFonts = env.getAllFonts();
int nFonts = allFonts != null ? allFonts.length : 0;
fontNames = new String[nFonts];
fontMap = new Hashtable();
String currentFamily = "";
int j = 0;
for ( int i = 0; i < nFonts; i++ ) {
Font font = allFonts[ i ];
System.out.println( allFonts[ i ] );
if ( font.canDisplay( sampleChineseCharacter )) {
currentFamily = font.getFamily();
Object key = fontMap.put( currentFamily, font );
if ( key == null ) {
// The currentFamily hasn't been seen yet.
fontNames[ j ] = currentFamily;
j++;
}
}
}
String tmp[] = fontNames;
fontNames = new String[j];
System.arraycopy( tmp, 0, fontNames, 0, j );
}
您可能必须在对象标记中传递以下参数:
<param name="java_arguments" value="-Dfile.encoding=utf-8" />
我发现这里的代码不足以满足我的需要。
我需要测试一个未知的输入字符串,以确定要使用的字体,因此,我需要检查每个字符。(见下文)
顺便说一句,font.canDisplayUpTo 方法不起作用。它可能会批准一种只能显示部分字符的字体。
所以,只需使用下面的代码。
Font[] allFonts;
GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment();
allFonts = env.getAllFonts();
Font targetFont = null;
for ( int i = 0; i < allFonts.length; i++ )
{
Font font = allFonts[ i ];
boolean canDisplayAll = true;
for (char c : text.toCharArray())
{
if (!font.canDisplay(c))
{
canDisplayAll = false;
break;
}
}
if (canDisplayAll)
{
logger.debug("font can display the text " + font.getName());
targetFont = font;
break;
}
else
{
logger.debug("cant display " + font.getName());
}
}