问题描述:
FengGUI不支持中文,输入中文时,接受到的是乱码(不能接受中文),没有任何显示。所以要解决此问题,首先是让其能正常接收中文,其次是让其能正常显示中文。这里是以fenggui的examples为例的。fenggui对文字的处理是:
第一步
启动程序,首先加载font文件及与之对应的png,读取font文件,将其内容放到hashtable<Character, CharacterPixmap>中,之后将png图片读到BufferedImage中。
第二步
当首次接受到文字时,调用ImageFont类的uploadToVideoMemory()(用了GL11的一些东西),同时借助fenggui的一些类,将上面的BufferedImage作为参数创建了一个ITexture对象,循环hashtable<Character,CharacterPixmap>,给所有的CharacterPixmap对象都设置ITexture,这样每一个CharacterPixmap对象就有了这个ITexture,同时,它还保存有从font文件中读出来的x, y, width, height, charWidth等信息。
第三步
再次接受到文字时,又从hashtable中得到它所对应的CharacterPixmap,从CharacterPixmap
取出ITexture,利用GL11.glBindTexture(GL11.GL_TEXTURE_2D,textureID);进行绑定。再通过对GL11的八个顶点坐标进行设置等。
之前fenggui不支持中文,原因主要在于它生成的贴图上面并没有中文字符,只有英文字母和常用的英文标点符号等。
让其正常接收到中文:
/*
* FengGUI - Java GUIs in OpenGL (http://www.fenggui.org)
*
* Copyright (c) 2005-2009 FengGUI Project
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details:
* http://www.gnu.org/copyleft/lesser.html#TOC3
*
* $Id: ExampleBasisLWJGL.java 654 2009-08-10 22:57:36Z marcmenghin $
*/
package org.fenggui.example;
import com.jmex.awt.input.AWTKeyInput;
import org.fenggui.actor.ScreenshotActor;
import org.fenggui.binding.render.lwjgl.EventHelper;
import org.fenggui.binding.render.lwjgl.LWJGLBinding;
import org.fenggui.event.InputEvent;
import org.lwjgl.LWJGLException;
import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.GL11;
import org.lwjgl.util.glu.GLU;
import javax.swing.*;
import java.awt.event.KeyEvent;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;
/**
* Examplary LWJGL app that shows the 'Everyhing' example.
*
* @author Johannes Schaback, last edited by $Author: marcmenghin $, $Date:2009-08-11 06:57:36 +0800 (星期二, 11 八月 2009) $
* @version $Revision: 654 $
* @todo Comment this class... #
*/
public class ExampleBasisLWJGL {
org.fenggui.Display desk = null;
private int lastButtonDown = -1;
private ScreenshotActor screenshotActor;
public static void main(String[] args) {
new ExampleBasisLWJGL().execute();
System.exit(0);
}
char chcode = 0;
private void readBufferedKeyboard() {
//check keys, buffered
Keyboard.poll();
while (Keyboard.next()) {
//若接受到的是中文
char character =Keyboard.getEventCharacter();
if (chcode == 0) {
chcode =character;
if (character> 127) {
return;
}
} else {
int temp =chcode;
chcode =(char) (character + (chcode << 8));
System.out.println((temp << 8) + "+" + (int) (character) +"=" + ((int) (chcode)));
}
try {
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
// sendEvent(keyCode, pressed, chcode);
if (Keyboard.getEventKeyState()) // if pressed
{
sendEvent(Keyboard.getEventKey(),true, chcode);
// desk.fireKeyPressedEvent(EventHelper.mapKeyChar(), EventHelper.mapEventKey());
} else {
sendEvent(Keyboard.getEventKey(),false, chcode);
// desk.fireKeyReleasedEvent(EventHelper.mapKeyChar(), EventHelper.mapEventKey());
}
chcode = 0;
}
});
} catch (InterruptedExceptione) {
e.printStackTrace();
} catch(InvocationTargetException e) {
e.printStackTrace();
}
// if(Keyboard.getEventKeyState()) // if pressed
// {
// desk.fireKeyPressedEvent(EventHelper.mapKeyChar(),EventHelper.mapEventKey());
// } else {
// desk.fireKeyReleasedEvent(EventHelper.mapKeyChar(), EventHelper.mapEventKey());
// }
}
}
private Map<Int, Char> characters = new HashMap<Int,Char>();
private static Int anInt = new Int(0);
private void sendEvent(int keyCode, boolean pressed, charcharacter) {
keyCode = AWTKeyInput.toAWTCode(keyCode);
System.out.println("in sendEvent :" + character);
try {
if (keyCode != 0) {
if (character== '\0') {
System.out.println("in sendEvent character='\\0'");
character = KeyEvent.CHAR_UNDEFINED;
}
if (pressed){
System.out.println("pressed : " + " character: " + character + ", int : " + (int) character);
desk.fireKeyPressedEvent(character,EventHelper.mapEventKey());
anInt.value = keyCode;
Char c = characters.get(anInt);
if (c == null) {
characters.put(new Int(keyCode), newChar(character));
} else {
c.value = character;
}
// if (character != KeyEvent.CHAR_UNDEFINED) {
// System.out.println("character notCHAR_UNDEFINED.");
// // desk.fireKeyPressedEvent(character, EventHelper.mapEventKey());
// }
}
if (!pressed){
anInt.value = keyCode;
System.out.println("!pressed : " + character);
// System.out.println((int) character + "," +(character > 255 && character < 65535));
if (character > 255 && character < 65535) {
char s = new String(new byte[]{(byte)(character / 256), (byte) (character % 256)},"gbk").toCharArray()[0];
System.out.println("ssss ssss ssss :" + s + " int : " + (int) s);
desk.fireKeyPressedEvent(s,EventHelper.mapEventKey());
desk.fireKeyReleasedEvent(s,EventHelper.mapEventKey());
} else {
desk.fireKeyReleasedEvent(character,EventHelper.mapEventKey());
}
}
}
} catch (Exception e) {
e.printStackTrace();
System.out.println(e.getMessage());
System.out.println("Exception ====");
}
}
private static class Int {
public Int(int value) {
this.value = value;
}
public boolean equals(Object obj) {
return obj instanceof Int&& ((Int) obj).value == value;
}
public int hashCode() {
return value;
}
int value;
}
private static class Char {
public Char(char value) {
this.value = value;
}
char value;
}
/**
* reads a mouse in buffered mode
*/
private void readBufferedMouse() {
int x = Mouse.getX();
int y = Mouse.getY();
InputEvent event = null;
// @todo the click count is notconsidered in LWJGL! #
if (lastButtonDown != -1 &&Mouse.isButtonDown(lastButtonDown)) {
event =desk.fireMouseDraggedEvent(x, y, EventHelper.getMouseButton(lastButtonDown));
} else {
if (Mouse.getDX() != 0 ||Mouse.getDY() != 0)
event =desk.fireMouseMovedEvent(x, y);
if (lastButtonDown != -1) {
event =desk.fireMouseReleasedEvent(x, y, EventHelper.getMouseButton(lastButtonDown));
lastButtonDown = -1;
}
while (Mouse.next()) {
if(Mouse.getEventButton() != -1 && Mouse.getEventButtonState()) {
lastButtonDown = Mouse.getEventButton();
event = desk.fireMousePressedEvent(x, y,EventHelper.getMouseButton(lastButtonDown));
}
int wheel =Mouse.getEventDWheel();
if (wheel !=0) {
event = desk.fireMouseWheel(x, y, wheel > 0, 1, 1);
}
}
}
//check if event did hit a widget
if (event != null &&event.isUIHit()) {
//ui hit
}
}
/**
*
*/
public void execute() {
try {
initEverything();
}
catch (LWJGLException le) {
le.printStackTrace();
System.out.println("Failed to initialize Gears.");
return;
}
mainLoop();
destroy();
}
/**
*
*/
private void destroy() {
Display.destroy();
}
private void mainLoop() {
while (!Display.isCloseRequested()) {
readBufferedKeyboard();
readBufferedMouse();
glRender();
Display.update();
}
}
/**
*
*/
private void glRender() {
GL11.glLoadIdentity();
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT |GL11.GL_DEPTH_BUFFER_BIT);
GLU.gluLookAt(10, 8, 8, 0, 0, 0, 0, 0,1);
// GL11.glRotatef(rotAngle, 1f, 1f, 1);
// GL11.glColor3f(0.42f,0.134f, 0.44f);
// rotAngle += 0.5;
// draw GUI stuff
desk.display();
screenshotActor.renderToDos(desk.getBinding().getOpenGL(),desk.getWidth(), desk.getHeight());
// hmm, i think we need to query themouse pointer and
// keyboard here and call the according
// desk.mouseMoved, desk.keyPressed, etc.
// methods...
}
/**
*
*/
public final void initEverything() throws LWJGLException {
Display.setDisplayMode(newDisplayMode(800, 600));
Display.setFullscreen(false);
Display.create();
Display.setTitle("Gears");
glInit(800, 600);
// initialize keyboard
Keyboard.create();
// build the gui
buildGUI();
screenshotActor = new ScreenshotActor();
screenshotActor.hook(desk);
}
// FengJMEInputHandler input;
public void buildGUI() {
// init. the LWJGL Binding
LWJGLBinding binding = newLWJGLBinding();
// init the root Widget, that spans thewhole
// screen (i.e. the OpenGL context withinthe
// Microsoft XP Window)
desk = new org.fenggui.Display(binding);
// input = new FengJMEInputHandler(desk);
// build a simple test FengGUI-Window
Everything everything = new Everything();
everything.buildGUI(desk);
}
private void glInit(int width, int height) {
// Go into orthographic projection mode.
GL11.glMatrixMode(GL11.GL_PROJECTION);
GL11.glLoadIdentity();
GLU.gluOrtho2D(0, width, 0, height);
GL11.glMatrixMode(GL11.GL_MODELVIEW);
GL11.glLoadIdentity();
GL11.glViewport(0, 0, width, height);
//set clear color to ... ugly
GL11.glClearColor(0.1f, 0.5f, 0.2f,0.0f);
//sync frame (only works on windows) => THAT IS NOT TRUE (ask Rainer)
Display.setVSyncEnabled(false);
}
}
fenggui支持中文,修改之处如下:
org.fenggui.binding.render.ImageFont文件:
public void process(InputOutputStream stream) throws IOException,IXMLStreamableException 方法中作如下修改:
public void process(InputOutputStream stream) throws IOException,IXMLStreamableException {
if (stream.isInputStream()) {
if(stream.startSubcontext("load")) {
String map =stream.processAttribute("map", "not-set");
String image= stream.processAttribute("image", "not-set");
map =((InputOnlyStream) stream).getResourcePath() + map;
image =((InputOnlyStream) stream).getResourcePath() + image;
loadFont(image, map);
stream.endSubcontext();
return;
} else if (stream.startSubcontext("create")){
String name =stream.processAttribute("fontName", "not-set");
StringtypeStr = stream.processAttribute("type", "not-set","plain");
int type =java.awt.Font.PLAIN;
if(typeStr.equalsIgnoreCase("plain"))
type = java.awt.Font.PLAIN;
else if(typeStr.equalsIgnoreCase("bold"))
type = java.awt.Font.BOLD;
else if(typeStr.equalsIgnoreCase("italic"))
type = java.awt.Font.ITALIC;
else
throw new IllegalArgumentException("Unknwown font type'" + typeStr + "'");
int size =stream.processAttribute("size", 16);
boolean antialiasing= stream.processAttribute("antialiasing", true, false);
// Stringalphabet = stream.process("alphabet", "not-set");
java.awt.FontawtFont = new java.awt.Font(name, type, size);
// String alphabetStr = stream.processAttribute("alphabet","unknown", "english");
StringalphabetStr = stream.processAttribute("alphabet","unknown", "utf8");
ImageFont f =null;
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);
this.height =f.height;
this.image =f.image;
this.texHashMap = f.texHashMap;
stream.endSubcontext();
} else
throw newIXMLStreamableException("neither <create> nor <load> found in<Font>", null);
}
}
org.fenggui.util.Alphabet中作如下修改:
增加
public static final Alphabet UTF8 = new Alphabet(ChineseAlphabet.getCharArray());
并修改默认为UTF8形式:
private static Alphabet defaultAlphabet =UTF8;
在org.fenggui.util包中新增ChineseAlphabet文件,该文件不包含英文字母等,因为Alphabet的带参构造方法
public Alphabet(char[] additionalChars)
{
String a = new String(additionalChars);
a += new String(alphabet);
alphabet = a.toCharArray();
}
private char[] alphabet = ("abcdefghijklmnopqrstuvwxyz" +"ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "`1234567890-="
+"~!@#€μ$%^&*()_+" + "[]{}\\|" + ":;\"'"+ "<>,.?/ ").toCharArray();
这个构造方法就已经包含了英文了。
ChineseAplhabet的源码:
package org.fenggui.util;
/**
* @author kaiying
*/
public class UTF8Alphabet {
public static char[] getCharArray() {
char[] chineseSupport = new char[20991];
//汉字
for (int i = 19968, j = 0; i <= 40959&&j < 20991; i++, j++) {
chineseSupport[j] =(char)i;
}
return chineseSupport;
}
}
当然这里没有特殊符号之类的,可以找到特殊符号的编码范围,再加上就行了。