问题描述
虽然在前面基础上,已经能接受并显示中文了,但每次运行程序都要重新画那么多字符,很慢。考虑利用FengGUI先生成自己的png图片及与之对应的font文件,之后运行时就导入这两个文件,这样就不会每次运行都重新画字符,将快很多。
解决方案
- 在fenggui中想实现中文的支持,但每次运行程序都得重新画字符,这样很慢,因为中文字符比英文字符多很多倍。
但fenggui提供了可以从外面引入png及xml的方法,这就表示可以使用自己的png图片库。
下面是生成png及与之对应的xml(这里写成了test.font文件,其实一回事)的方案,当然支持中文的部分不只是这一点点,应该结合前面的修改来看,才会是完整的支持中文的解决方案。
最终生成的font文件大小有8M多,png有480多K。
在fenggui中生成与png文件对应的font文件:
font文件主要格式如下:
<?xml version='1.0' encoding='utf-8'?>
<Font>
<CharacterPixmap x="72" y="145"width="15" height="29" charWidth="15">
<character><![CDATA[~]]></character>
</CharacterPixmap>
// ..... 这种在实际应用font文件时不能作为注释
</Font>
x, y, width, height表示这个字符所在的格子(一个rectangle,矩形)的位置及大小,其中(x,y)是该矩形的最下角的坐标,左上角的坐标
为(x, y + height),右下角的坐标为(x +width, y), 右上角的坐标为(x + width, y + height)。
charWidth表示字符所占的宽度。
第一步:
修改代码:
org.fenggui.util.CharacterPixmap源文件中, 修改之处的源代码:
public CharacterPixmap(ITexture texture, int x, int y, int width, int height,char c, int charWidth)
{
super(texture, x, y, width, height);
this.charWidth = charWidth;
character = c;
}
修改之后的代码:
File file;
FileOutputStream fos;
public CharacterPixmap(ITexture texture, int x, int y, int width,int height, char c, int charWidth) {
super(texture, x, y, width, height);
this.charWidth = charWidth;
character = c;
//生产font文件
if (file == null) {
file = newFile("D:\\test.font");
}
try {
if (fos == null) {
fos = newFileOutputStream(file, true);
}
String s = "<CharacterPixmap x=\"" + x + "\" y=\"" + y +"\" width=\"" + width + "\" height=\""+ height + "\" charWidth=\"" + charWidth+"\">\n" +
" <character><![CDATA[" + c +"]]></character>\n" +
" </CharacterPixmap>\n\n";
fos.write(s.getBytes());
} catch (IOException e) {
System.out.println("写入test.font文件时发生异常!");
e.printStackTrace();
}
}
这里写入font文件的变量名x, y, width,height, charWidth等要与下面解析它们的这代码中的一致:
org.fenggui.util.FontSAXHandler类:
@Override
public void startElement(String uri, String localName, StringqName, Attributes attributes) throws SAXException
{
if (qName.equals("CharacterPixmap"))
{
x = 0;
y = 0;
width = 0;
height = 0;
charWidth = 0;
x =Integer.parseInt(attributes.getValue("x"));
y =Integer.parseInt(attributes.getValue("y"));
width =Integer.parseInt(attributes.getValue("width"));
height = Integer.parseInt(attributes.getValue("height"));
charWidth =Integer.parseInt(attributes.getValue("charWidth"));
}
else if (qName.equals("character"))
builder = new StringBuilder();
}
第二步:
在包org.fenggui.util.fonttoolkit中的FontFactory类里, 打开这句代码:
saveImageToDisk(bi, "D:\\test.png");
生产test.png图片
第三步:
在org.fenggui.binding.render.ImageFont类的
public void process(InputOutputStream stream) throws IOException,IXMLStreamableException方法中
打开这段代码:
boolean antialiasing = stream.processAttribute("antialiasing", true,false);
java.awt.FontawtFont = new java.awt.Font(name, type, size);
StringalphabetStr = stream.processAttribute("alphabet","unknown", "utf8");
if(alphabetStr.equalsIgnoreCase("utf8"))
f = FontFactory.renderStandardFont(awtFont, antialiasing,Alphabet.UTF8);
else if(alphabetStr.equalsIgnoreCase("english"))
f = FontFactory.renderStandardFont(awtFont, antialiasing,Alphabet.ENGLISH);
else if(alphabetStr.equalsIgnoreCase("german"))
f = FontFactory.renderStandardFont(awtFont, antialiasing,Alphabet.GERMAN);
else if(alphabetStr.equalsIgnoreCase("french"))
f = FontFactory.renderStandardFont(awtFont, antialiasing,Alphabet.FRENCH);
else if(alphabetStr.equalsIgnoreCase("danish"))
f = FontFactory.renderStandardFont(awtFont, antialiasing,Alphabet.DANISH);
else if(alphabetStr.equalsIgnoreCase("estonian"))
f = FontFactory.renderStandardFont(awtFont, antialiasing,Alphabet.ESTONIAN);
同时在该方法中关闭:
// f = newImageFont("D:\\test.png", "D:\\test.font");
这样就可以生产png图片以及与之相对应的font文件了,但是font文件格式还不对,还得手动在最前面加上
<?xml version='1.0' encoding='utf-8'?>
<Font>
其中<?xml version='1.0' encoding='utf-8'?>这句代码前面不能有空格,以前好像遇到有空格时出过问题的情况的。
再font文件最末加上</Font>结束标签。
完成以上步骤之后就完成了fenggui中完整的png图片与font文件的生产了,由于中文汉字很多,所以生成这两个文件需要很长一段时间。
生产了这两个文件之后,第二次运行时,需要注意一下几步:
第一步:
关闭这段代码:
//生产font文件
// if (file == null) {
// file = newFile("D:\\test.font");
// }
//
// try {
// if (fos == null) {
// fos = newFileOutputStream(file, true);
// }
// String s = "<CharacterPixmap x=\"" + x + "\" y=\"" + y +"\" width=\"" + width + "\" height=\""+ height + "\" charWidth=\"" + charWidth+"\">\n" +
// " <character><![CDATA[" + c +"]]></character>\n" +
// " </CharacterPixmap>\n\n";
// fos.write(s.getBytes());
// } catch (IOException e) {
// System.out.println("写入test.font文件时发生异常!");
// e.printStackTrace();
// }
第二步:
关闭:
// saveImageToDisk(bi, "D:\\test.png");
第三步:
打开 f = new ImageFont("D:\\test.png","D:\\test.font");
关闭:
// booleanantialiasing = stream.processAttribute("antialiasing", true, false);
// java.awt.Font awtFont = new java.awt.Font(name, type, size);
// StringalphabetStr = stream.processAttribute("alphabet","unknown", "utf8");
// if(alphabetStr.equalsIgnoreCase("utf8"))
// f = FontFactory.renderStandardFont(awtFont, antialiasing,Alphabet.UTF8);
// else if(alphabetStr.equalsIgnoreCase("english"))
// f = FontFactory.renderStandardFont(awtFont, antialiasing,Alphabet.ENGLISH);
// else if(alphabetStr.equalsIgnoreCase("german"))
// f = FontFactory.renderStandardFont(awtFont, antialiasing,Alphabet.GERMAN);
// else if(alphabetStr.equalsIgnoreCase("french"))
// f = FontFactory.renderStandardFont(awtFont, antialiasing,Alphabet.FRENCH);
// else if(alphabetStr.equalsIgnoreCase("danish"))
// f = FontFactory.renderStandardFont(awtFont, antialiasing,Alphabet.DANISH);
// else if(alphabetStr.equalsIgnoreCase("estonian"))
// f = FontFactory.renderStandardFont(awtFont, antialiasing,Alphabet.ESTONIAN);
当然,fenggui自身也有writeFontData方法,功能是写对应的font文件,但我每次使用都会报错,干脆自己弄了一个。
最后一点小问题:
在org.fenggui.util.Alphabet类中,必须默认使用UTF8,否则,本次运行是支持中文,但生成的png图片库中并没有将中文字符写进去,所以下一次使用自己生成的font文件及png图片时就会出问题,具体原因还在思考中。