Unicode

2024-08-23

Unicode 篇1

MiniGUI采用了面向对象的技术实现了图形抽象层(GAL)、输入抽象层(IAL)以及多字体和多字符集的支持。GAL和IAL大大提高了MiniGUI的可移植性,并将底层图形设备和上层接口分离开来。MiniGUI采用逻辑字体实现多字体和多字符集处理。这一技术成功应用了面向对象技术,通过单一的逻辑接口,可以实现对各种字符集以及各种字体的支持[4]。

1 MiniGUI中TrueType字体的实现

1.1 TrueType字体简介

TrueType是Apple公司和Microsoft公司合作开发的页面描述语言(Page Description Language,PDL)TrueImage中的字形描述部分。TrueType字体(简称TTF)采用直线和二次Bezier曲线来描述字符的轮廓,结合了光栅技术和矢量技术的优点,克服了以往所有点阵字体、矢量字体和向量轮廓字体的缺点,字体可以任意放大、缩小、旋转和变形而不会影响输出质量,提供了真正的设备无关性。二次Bezier曲线既能保证轮廓曲线的光滑性,又有利于提高字形还原速度。另外,TrueType所特有的丰富的指令集,不仅弥补了TTF的二次曲线描述轮廓的不足,而且增强了TTF字形描述的灵活性。若要提高字体的质量,不仅可以通过数据信息来实现,而且可通过增加指令来进行。Microsoft公司从Windows 3.1开始就采用TrueType字体技术。随着Windows的流行,TrueType已经成为事实上的字形描述标准之一[5]。

1.2 TrueType字体的分析及实现

1.2.1 TrueType字体的数据结构

本文采用FreeType这个中间件来实现TrueType字体支持。在MiniGUI设备字体定义中,有一个data字段可用来保存设备字体相关的数据结构。对TrueType字体来讲,我们使用TTFGLYPHINFO和TTFINSTANCEINFO两个数据结构来存储TrueType字体的文字轮廓信息和实例信息。

如前面所说,TTFGLYPHINFO和TTFINSTANCEINFO数据结构来存储TrueType的图元信息和实例信息。其中TTFGLYPHINFO中的成员valid是用来判断该设备字体是否初始化完毕。

1.2.2 TrueType字体的字体操作集freetype_font_ops

MiniGUI中的设备字体操作集针对每种设备字体类型而定义,包括对这种设备字体的各种操作函数。TrueType字体的字体操作集freetype_font_ops的结构成员及功能如表1所示。

1.2.3 InitFreeTypeFont和TermFreeType Fonts函数

这两个函数负责整个TrueType字体的初始化和终结。

InitFreeTypeFonts的主要任务是:初始化TTF字库,并向系统注册用来处理TrueType字体的字体操作集freetype_font_ops。

TermFreeTypeFonts则是注销TrueType字体,关闭TTF字库。

1.2.4 向配置文件MiniGUI.cfg添加TrueType字体支持

MiniGUI在初始化时,要读取MiniGUI.cfg中的字体定义并装载指定字体文件,装载后的字体在MiniGUI内部称为“设备字体”。设备字体定义了这种字体的样式名、风格、大小以及它所支持的字符集。MiniGUI在创建逻辑字体时,要根据已装载的设备字体,以及应用程序指定的字体类型、样式名、大小、字符集等信息寻找合适的设备字体来显示文本[1]。

在MiniGUI.cfg文件中的systemfont段添加下面代码:

2 MiniGUI中Unicode字符集UTF-16LE编码方式的实现

MiniGUI对多字符集的支持通过逻辑字体接口来实现。应用程序在显示文本时,通常要建立逻辑字体,并指定该字体使用的字符集编码名称。在创建逻辑字体之后,应用程序就可以使用该逻辑字体显示文本或者分析文本结构。

Unicode可以用来表示所有语言的字符,而且是定长双字节(也有四字节的)编码,包括英文字母在内。所以可以说它是不兼容iso8859-1编码的,也不兼容任何编码。它具有多种编码方式,常见的有:UTF-8,UTF-16,UTF-32。而UTF-16分为UTF-16LE和UTF-16BE,本文采用UTF-16LE编码方式进行文本显示和输出。

常用的文本输出函数有Text和DrawText等,其中只有DrawText函数不支持UTF-16编码方式的文本输出。本文将提供支持Unicode字符集UTF-16LE编码的DrawText函数[1]。

2.1 DrawText函数相关源代码导读

要使DrawText函数支持UTF-16LE编码,需更改libminigui-1.6.10/src/newgdi目录下的Text.c文件的部分代码,改写方法如下:

1)Text.c的523行char_len=1改为char_len=is_utf16_logfont(pdc)?2:1。

2)Text.c的592行if(is_utf16_logfont(pdc))return-1注释掉。

3)Text.c的536行(*nChar)++下一行添加if(is_utf16_logfont(pdc))(*nChar)++。

4)Text.c的542行char_len=1改为char_len=is_utf16_logfont(pdc)?2:1。

以上修改的原因是:UTF-16LE编码是采用两字节表示字符,包括控制字符。以上修改确保了控制字符采用两字节输出。

2.2 文本转换接口函数MBS2WCSEx

MiniGUI通过MB2WCEx和MBS2WCSEx这两个接口函数实现多个字符集/编码(如GB2312、ISO8859、UTF-8、GBK、BIG5等)和UNICODE内码相互转换功能,前者一次只转换一个字符,后者一次可转换多个字符,因此本文采用MBS2WCSEx函数进行文本转换[1]。

MBS2WCSEx函数原型如下:int GUIAPI MBS2WCSEx(PLOGFONT log_font,void*dest,BOOL wc32,const unsigned char*mstr int mstr_len,int n,int*conved_mstr_len);

参数说明:

log_font:逻辑字体

dest:用于存放已转换的宽字符串的缓冲区

wc32:判断这个unicode字符是32位还是16位,TRUE表示是32位的,FALSE表示是16位的

mstr:多字节字符串

mstr_len:多字节字符串的长度

n:缓冲区的长度

conved_mstr_len:已正确转换的宽字符串长度的返回指针,一般为NULL

2.3 对TextOut函数和DrawText函数进行外部封装

为了方便对支持Unicode字符集UTF-16LE编码方式的文本输出,以下是TextOut函数和DrawText函数的封装的部分代码。

2.3.1 自定义枚举类型数据结构如下:

2.3.2 创建支持Unicode字符集UTF-16LE编码方式的不同字体大小的TrueType字体

FontUnicode[FONT_UN ICODE_SIZE_12]=CreateLogFont("ttf","sic",FONT_CHARSET_UTF16LE,FONT_WEIGHT_REGULAR,FONT_SLANT_ROMAN,FONT_SETWIDTH_NORMAL,FONT_SPACING_CHARCELL,FONT_UNDERLINE_NONE,FONT_STRUCK-OUT_NONE,12,0);

FontUnicode[FONT_UNICODE_SIZE_16]=CreateLogFont("ttf","sic",FONT_CHARSET_UTF16LE,FONT_WEIGHT_REGULAR,FONT_SLANT_ROMAN,FONT_SETWIDTH_NORMAL,FONT_SPACING_CHARCELL,FONT_UNDERLINE_NONE,FONT_STRUCK-OUT_NONE,16,0);

FontUnicode[FONT_UNICODE_DEFAULT]=NULL;

2.3.3 TextOut函数和DrawText外部封装接口

int TextOutUnicode(HDC hdc,int x,int y,const char*spText,FONT_UNICODE newFontIndex,FONT_TEXT originalChaset)

int DrawTextUnicode(HDC hdc,const char*pText,int nCount,RECT*pRect,UINT nFormat,FONT_UNICODE newFontIndex,FONT_TEXT originalChaset)

2.4 向配置文件MiniGUI.cfg中添加Unicode字符集UTF-16LE编码方式的TrueType字体支持

将从Windows下提取的kaiti.ttf字体文件添加在系统的usr/local/lib/minigui/res/font目录下,并将MiniGUI.cfg文件中的truetypefont段的代码改为下面的代码:

3 结束语

通过对TTF字体的技术原理的概述,分析了MiniGUI中TrueType字体的数据结构、字体操作集、字体初始化和字体终结函数,从而实现了对TrueType字体的支持。

通过对MiniGUI中的Text.c源文件进行分析、导读、修改实现了DrawText函数对UTF-16LE编码方式的支持。

通过对文本转换函数MBS2WCSEx的分析和应用,实现了多字符集/编码向Unicode内码的转换,进而实现了对支持Unicode字符集的文本输出。

最后,根据上述方法在Ubuntu版本Linux系统上实现了对Unicode字符集UTF-16LE编码方式的TrueType字体的文本输出和显示。

参考文献

[1]魏永明.MiniGUI编程指南[EB/OL].http://www.minigui.com/fileadmin/download/MINIGUI-PROG-GUIDE-V2.0-4C.pdf.

[2]魏永明.MiniGUI用户手册[EB/OL].http://www.minigui.com/fileadmin/download/MINIGUI-USER-MANUAL-V2.0-4C.pdf.

[3]魏永明.MiniGUI技术白皮书[EB/OL].http://www.minigui.com/fileadmin/download/MiniGUITechWhitePaper-2.0-4C.pdf.2008,10.

[4]魏永明.MiniGUI体系结构之三:逻辑字体以及多字体和多字符集实现[EB/OL].http://www.ibm.com/developerworks/cn/linux/embed/minigui/minigui-7/index.html.

Unicode编程类笔试题 篇2

将程序改成Unicode编程需要做哪些修改?

window 2k以后的系统底层都是基于Unicode的,就算你调用ANSI的API(以A结尾比如SetWidowsTextA),系统也会在你的进程默认堆上动态分配一块内存,存放转换后的Unicode字符串,然后把转换后的字符串传递给API,如果调用了返回值为ANSI字符串的API,Windows会在后台进行相反的转换,

其实VC中进行Unicode编程也不麻烦,大概如下:

1.为工程添加UNICODE和_UNICODE预处理选项,在VC.net中就是 项目 ->属性 ->c/c++ ->预处理器 在“预处理定义”中加入这两个宏定义(vc6中 project ->settings ->c/c++ ->general 中的 Preprocessor definitions).

2.Include (一般在stdafx.h中)然后把所有使用char*定义变量的地方换为LPTSTR/TCHAR*或LPCTSTR/const TCHAR*(对应于const char*).

3.把所有的字符串常量用_T宏包起来,比如 TCHAR* szText = _T(“我的Text”);

4.所有的C库字符串操作函数也做相应的替换,比如

strlen ->_tcslen

strcat ->_tcscat

strcmp ->_tcscmp

......

注意,这些函数中的."文本长度"均为字符个数,而非char个数具体参看MSDN.

5.API调用一般不用做特殊处理,当定义了UNICODE和_UNICODE后,所有的API都会被宏指向W结尾的版本(不定义则指向A结尾的版本).

【Unicode】推荐阅读:

上一篇:宋祖英演唱风格论文下一篇:面向目标

热搜文章

    相关推荐