2007-12-25 09:55:38
摘 要:Microwindows是运行在嵌入式系统上的开源GUI软件,对嵌入式Linux操作系统具有良好的支持。本文介绍了在uClinux上移植icrowindows的过程;提出了三种解决Microwindows中文化的方法:直接加载中文字库,添加Truetype字体驱动模块Freetype2,修改图形引擎支持国际化与本地化:并对这几种方法进行了分析和比较。
1 引言
嵌入式GUI系统是嵌入式系统中实现友好人机界面的关键技术,应用于嵌入式的GUI系统必须具备体积小、反应快、高可靠性、可移植性好以及可裁减等特点,对于实时系统还需要有时实方面的要求。目前,流行的嵌入式GU1系统有Microwindows、MiniGUI、Qt/Embedded等。其中Microwindows以其开放的源代码、可以裁减到100k的内核、与Win32兼容的API以及高度的可移植性在嵌入式系统中得到广泛的应用。
根据高清数字电视UI产品开发需要,作者在uClinux上移植了Microwindows。为了实现中文化支持,分别从不同层次、不同角度,通过直接加载中文字库、添加Truetype字体驱动模块Freetype2、修改图形引擎支持国际化与本地化等方法对Microwindows的中文化进行了研究和分析,并对几种方
法进行了比较。基于本项目对多国语言的需求,实际采用了基于Freetype2的Truetype中文字库,将国际化与本地化嵌入图形引擎实现中文化,该方法在实际应用中取得了良好的效果。
2 Microwidows系统介绍
Microwindows是一个开放源码的嵌入式GUI项目,目的在于把现代图形视窗环境的特性引入到小型设备上。MicroWindows起源于NanoGUl项目,目前的发布包括Microwindows和Nano-X两部分代码。MicroWindows可以运行在UNIX、X11、ELKS、MSDOS、RETMS等系统上,支持ARM、MIPS、PowerPC、i386等处理器结构。由于和微软的Windows注册商标存在冲突,从2005年1月起,MicroWindows改名为Nano-X Window System。
Microwindows系统采用分层的设计方案以满足不同的实现需要。总体分为三层:最下面的设备驱动层、中间的图形引擎层、面向应用程序的API接口层(图1)。设备驱动部分提供了屏幕、鼠标/触摸屏、键盘以及其它I/O设备的实际操作,并向上提供统一接口以实现设备无关图形引擎。中间层实现
了画点、画线、多边形、剪切区以及颜 {MOD}模式设置等功能。Microwindows提供了ECMA APIW 和Nano-X APIs两套不同标准的API,分别兼容win32和X Window,其它系统上编写的应用程序可以很容易移到Microwindows上运行。
图1 Microwindows的体系结构
3 移植Microwindows
Microwindows的最新版本已经更新到0.91。我们采用了比较稳定的发布版0.90版,0.90版提供了放多新增功能,并修止0.89版的一些BUG。增强和新增功能主要包括:对新的NXLIB项目的支持,内置触摸屏校准与一些新的基于ARM平台的硬件支持;改善x11的屏幕驱动与绘图速度:字体的增
强功能,支持FreeType2,新的BDF字体,支持中文、日文、韩文等DBCS多字节字库编码(BIG5,GB2312,EUCCN,EUCKR,EUCJP,JISX0213)。可以从
ftp://microwindows.censoft.com/pub/microwindows/microwindows.0.90tar.gz下载源代码。
3.1 工作平台
我们开发的目标硬件平台是基于BroadCom 公司的BCM7028高清数字电视芯片,内核是基于MIPS结构的R5000处理器。宿主机采用Redhat9.0,通过串口进行调试。在移植Microwindows之前,我们已经将uClinux移到BCM7028开发板上,通过NFS加载uClinux内核到目标机上。
3.2 硬件抽象层的移檀
Microwindows的分层体系结构,使其在不同平台上的移植变得相当容易。由于硬件抽象层为图形引擎内核提供了设备无关的输入输出接口,因此将其移植到目标平台上一般只需要根据实际情况提供相应的输入输出设备驱动就可以了。在硬件抽象层中,将没备分为两大类:显示相关设备和输入
相关设备。其实现于src/drivers下,其中以scr开头的为显示设备驱动程序,以mou和kbd开头的分别为鼠标和键盘驱动程序,还有以touchscreen开头的触摸屏驱动程序等。
Microwindows图形引擎支持VGA、X11、FrameBuffer等显示输出模式。在嵌入式系统中,由操作系统内核提供基于FrameBuffer的显示设备驱动,Microwindows通过配置文件config指定使用FrameBuffer作为底层图形驱动方式就可以了,一般不需要修改这部分。鼠标、键盘等输入设备的驱动都是基于标准的访问接口实现的,这与Linux下的设备驱动程序基本相同,在我们的系统中,采用了类似键盘的遥控输入设备。下面是键盘驱动的接口定义:
typedef struct-kbddevice{
int(* Open)(struct-kbddevice pkd);//打开设备
void(* Close)(void);//关闭设备
void (* GetModifierlnfo) (MWKEYMOD *modifers,MWKEYMOD *curmodifiers);//获取组合键相应状态信息
int(* Read)(MWKEY * bur,MWKEYMOD *modifiers,MWSCANC0DE *scancode);//获取键盘按键状态信息
int(*PoIO(void);//实现select调用的替代方法
}KBDDEVICE;
3.3 修改配置文件
完成了新硬件的驱动移植,接下来就是对Microwindows的功能进行配置与裁减,最终获得符合我们要求的GUI系统。在src下有一个config文件,用来对microwindows进行配置,根据一般的移植过程,可以按如下顺序进行修改:
1)定义Microwindows的目标平台
Microwindows支持的目标平台有:LINUX-NATIVE、LINUX-ARM、LINUX-MIPS、LINUX-POWERPC多种平台,默认为LINUX-NATIVE,根据我们的平台修改为:
ARCH = LINUX-MIPS
2)编译支持的库
提供选择的API库有microwin、nano-X、nanowidget、object frameworks,在我们的系统中选择了Win32风格的microwin,如下所示:
MICROWIN = Y
3)像素类型设置
设置像素的颜 {MOD}模式类型,Microwindows支持1、2、4、8、16、24、32位不同的颜 {MOD}模式,其典型设置为:
SCREEN- PIXTYPE = MWPF-TRUECOLOR0888 //32位真彩 {MOD}
4)图片格式支持
是否支持图片加载与显示,一般为了显示更个性化的界面,必须支持一种图片格式。默认为支持BMP、PNG、PNM、XMP等。
5)字体支持
一般系统支持几种内建字体,如果只显示英文,不需要修改这部分。但是我们的系统必须支持中文,因此这部分需要修改,现在为了移植简单,暂时不修改。
6)显示模式设置
Microwindows是与X Window兼容的图形系统,基于Microwindows的应用程序可以X Window 的方式和FrameBuffer的方式运行。在嵌入式系统中,我们选择基于FrameBuffer的驱动方式。
X11 = N
FRAMEBUFFER = Y
其它的选项基本上可以使用默认值,为了使系统最小,甚至可以关闭大部分的功能选项,如不需要的字体与图片格式支持等。
3.4 预编译与安装
在嵌入式系统中增加新的功能,有两种方法:一是在调试阶段,将需要的部分先编译,生成相应的库文件和应用程序,通过指定的挂载点放在系统的根文件系统中。二是开发好后,直接作为系统的一部分,编译进内核。我们采用第一种方法,Make生成相应的库文件,如果遇到编译出错,可能是相应选项得不到支持,或缺少相应库文件及包。可以关闭相应选项或确认是否存在需要的文件后重新编译。编译通过后,将src/lib下的库文件拷贝到uClinux的/usr/lib库目录下。下面修改Microwindows配置或内核后,都需要进行重新编译和安装。
4 Microwindows的中文化
4.1 中文编码与Unicode编码
中文不同于ASCII字符,一个中文需要2个字节来编码,通用的中文编码标准有GB2312、GBK、GB18030、BIG5(繁体),在嵌入式系统中我们采用GB2312标准,也是国家标准。为了区别中文与基本的ASCII字符,汉字的编码的每个字,最高位均为1,而0-127之间的编码用于基本的ASCII字符,因此我们可以同时显示中文与英文,而不会出现问题。而不同的多字节编码之间是不容易区分的,比如中文与日文,还有拉丁文,因此一些系统在进行处理的时候,会把不同的编码转成为通用的UniCode编码,Unicode编码规则是每个字符采用2字节或4字节进行编码,基本包括了世界上所有字符的编码。
4.2 直接加载中文字体
Microwindows内建了对中文的支持,通过下载中文字库包,修改config文件,可以让Microwindows支持简单的中文输出,具体实现如下:
1)从
ftp://microwindows.censoft.com/pub/microwindows/microwindows.fonts0.90.tar下载中文字库包,解压后拷贝fonts/chinese和fonts/truetype(见3.3节)到uClinux/fonts目录。
2)修改config文件如下:
HAVE-HZK-SUPPORT = Y
HZK-FONT-DIR = "/fonts/chinese"
3)修改应用程序,住输出中文的前后,加入如下语句:
HGDIOBJ flewfont,oldfont;
newfont=CreateFont(12,//可以设置12或16
0,0,0,0,0,0,0,0,0,0,0,
FF-DONTCAREIDEFAULT-PITCH,
"HZKFONT" //HZKFONT 为简体,HZXFONT为繁体
);//创建汉字字体
oldfont = SelectObject(hdc,newfont);//使用汉字字体
//这里调用DrawTextO进行输出
Deleteobject(Selectobject(hdc,oldfont));//,恢复旧字体
4.3 添加Truetype字体驱动模块Freetype2
Microwindows增加了对Freetype2的支持,FreeType2是TTF矢量字体的图形引擎库,通过引入Freetype2,使得Microwindows可以支持任何在Windows下使用的TTF、TTC字体库。具体实现如下:
1) 载Freetype2的源代码,可以从
http://www.freetype.org下载最新的2.1.1O发布版。解压编译后,生成libffeetype.a库文件,拷贝到uClinx的/usr/lib库目录下。
2)拷贝所需字库文件到uClinux的/fonts/truetype目录下,如simhei.ttf(简体黑体)、simson.fit(简体宋体)。
3)修改config文件如下:
HAVE-FREETYPE-2-SUPPORT = Y
HZK-FONT-DIR =/usr/include
LIBFT2LIB =/usr/lib/bfreetype.a
4)修改应用程序的CreateFont函数如下:
newfont=CreateFont(12,//可以设置为任意值
0,0,0,0,0,0,0,0,0,0,0,
FF-DONTCAREIDEFAULT-PITCH,
"simson.ttP" //设置为字库文件名
);//创建汉字字体
5)修正Freetype2的编码问题
通过输出中文进行验证,出来的并不是预期的结果,而字符的输出是正确的。这是因为Freetype2字库引擎对文本的输入是按Unicode编码处理的(这与3.2节中加载中文字库是不同的,前者是按ASCII处理的)。
在文件src/engine/font-freetype2.C 的freetype2-drawtext(…)函数中有明确的说明如下:
static void freetype2-drawtext(PMWFONT pfont,PSD psd,MWC00RD ax,
MWCOORD ay,const void * text,int CC,MWTEXTFLAGS flags);
//text:16位Unicode编码字符串
//co:字符串字符个数
再看一下文本输出API函数:DrawText、DrawTextA、DrawTextW 与freetype2 drawtext的关系,其中DrawText被定义为宏#define DrawText DrawTextA,DrawTextA 与DrawTextW 实现基本相同,其中DrawTextA接受ASCII字符,DrawTextW 接受宽字符。
DrawText的内部实现如下(--<表示调用,-<表示指针):
a)DrawText--< MwDrawText--< MwExtTextOut--< GdText
b)GdText调用gr-pfont-c)其中gr-pfont- 当用DrawText输出中文时,在GdText函数内有一个从ASCII到Unicode的转换,可是这个转换并没有解决问题,这一点可以从src/engine/devfont.C 的GdConvertEncoding函数中得到验证,此函数只是简单在每一个ASCII编码前加上一个0字节转为双字节,根本不符合GB2312到Unicode的转换规则,从而导致了freetype2 drawtext的输出错误。那么,是否可以象Win32那样直接如下调用DrawTextWO实现呢?
DrawTextW (……TEXT("要输出的文本")……);
确实在Microwindows下也定义了如下的字符串转换的宏,可惜没有实现。
#define TEXT(quote) quote
#define TEXT(quote)- TEXT(quote)
由以上分析可得,Freetype2的中文化还需要进行编码转换,下面给出了两种解决从GB2312到Unicode的方法:
方法一:使用iconv编码转换库
Libiconv.a提供三个转换接口函数来实现编码转换,要包含头文件iconv.h,分别介绍如下:
iconv-t iconv-open(char* to-codeset,char *from-codeset);
//打开转换句柄,
size-t iconv(iconv-t cd,char* *InBuf,size-t InBytesLeft,
char* *OutBuf,size-t OutBytesLeft);
//进行转换
int iconv-close(iconv-t cd)
//关闭转换句柄
方法二:使用setlocale进行转换
setlocale是与系统locale设置相关的函数,即系统本地化设置,介绍如下:
string setlocale(string category,string locale);
//设置本地化属性,主要是字符集和语言相及关信息
size-t mbstowcs(wchar-t* wcstr,const char *mbstr,size-t count);
//将多字节字字符串转换为Unicode字符串
size-t wcstombs(char* mbstr,const wchar-t* wcstr,size-t count);
//将Unicode字符串转换为多字节字字符串
当设置如下时,可以实现GB2312到Unicode的转换:
Setlocale(LT-CTYPE,"zh-CN.GB2312");
以上两种方法均可实现GB2312字符集到Unicode编码的相互转换问题,不仅适用于中文,也适用于其它DBCS字符集的情况。
4.4 修改图形引擎实现本地化和中文化
软件中引入国际化与本地化是实现软件通用化的基本方法。在21世纪信息化高度发达的时代,软件国际化与本地化越来越受到人们的高度重视,尽管Microwindows支持多种语言文字,但要实现灵活的多国语言支持,还需要进一步的改进与完善。下面是通过修改图形引擎,结合Linux的Locale设置实现的软件运行时多种语言任意切换的功能。实现如下:
1)Microwindows的字体设置
Microwindows的字体设置并不是在窗口创建时进行初始化的,而是在窗体第一次绘制时调用GetDC获取设备上下文时设置的,这是创建窗口的一种优化技术,如下所示:
调用关系如下:GetDC()-<GetDCEx()(src/mwin/wingdi.C)
DC WINAPI GetDCEx(HWND hwnd,HRGN hrgnClip,DW0RD flags)
{
HDC hdc;
if(!hwnd)
hwnd=rootwp;
//不是第一次调用,直接返回设备句柄
if(hwnd-return hwnd-hdc=GdItemNew(struct hdc)}//为窗口创建设备句柄
//设置窗口设备句柄的字体
hdc-
hwnd-由于GetDCExO是所有窗口显示必须调用的函数,因此通过修改hdc-2)加入FreeType2内建字体支持,支持本地化为了加入我们需要的默认字体,可以创建基于Unicode编码的Freetype2内建字体,在src/mwin/wingdi.C中加入以下代码
#define FONTNAME "simson"
static MWFONTOBJ OBJ-FREETYPE-FONT{
{OBJ-FONT,TRUE},
NULL,
FONTNAME;//字体名
};
//创建FreeType作为内建字体
MWFONTOBJ *GetFreeTypeFontOBJ()
{
Static PMWFONT pfont=NULL;
MWFONTOBJ pFont=&OBJ-FREETYPE-FONT;
if(!pfont)
{
pFont-< pfont= GdCreateFont(&srcde V,"",16,NULL);
pFont-< font= pfont;
}
return pFont;
}
3)使用setlocale进行编码转换,将前面的Setlocale(LTCTYPE,"zh-CN.GB2312")修改为Setlocale(LT-CTYPE,CHARSETNAME)。
最后,通过将字体名FONTNAME 与字符集名CHARSETNAME与作为环境变量进行传人,一个支持多字体多语言切换的Microwindows就实现了。
4.5 中文化方法小结与比较
1)直接加载中文字库是Microwindows自带的最容易实现的一种中文化方法。其优点是实现简单,容易操作:缺点是只支持固定的12和16两种高度的点阵字体,而且必须在应用程序中指定所用字体。
2)通过引入Truetype字体驱动模块实现中文化是比较理想的方案,FreeType2不仅对TrueType字库提供了良好的支持,而且完全兼容微软的TTF字库。其优点是字形美观、字体大小可以任意变化;可选用的字体库多;兼容其它编码的字体库,为支持多国语言提供了条件。缺点是实现比较复杂,不仅需要下载Freetype2的库,还要修止其中的编码问题:另外对嵌入式的系统而言,额外的内存空间开销也是不利的因素。
3)修改图形引擎实现本地化和中文化是软件国际化的一部分。通过引入Freetype2、修改窗口句柄的字体加载机制,将Microwindows图形系统与Linux系统中的Locale连接起来,使Microwindows具备了支持软件本地化的能力。该方法是对Microwindows的进一步改进与功能增强,是Microwindows中文化的高级方法。其优点是不仅解决了中文化问题,同时具有良好的适应性和更大的灵活性。其缺点是实现复杂,需要更多的系统支持和开销。
综上所述,我们可以用不同的方法来实现Microwindows的中文化,但各种方法的实现难度和代价不尽相同,用户可以根据实际需求进行选择。
5 总结
随着嵌入式技术的不断成熟与发展,功能强大、可移植性好的GUI系统必将在嵌入式系统中得到广泛的应用。Microwindows以其开放的源代码、与Win32兼容的API接口以及在多种不同软、硬件平台上良好的可移植性,已经成为嵌入式GUI系统的理想选择;尽管在实际开发中还需要一定的改进与优化,但这完全不影响它强大的功能与实际运行效果。