第17章 STemWin外语支持
本期教程的主要内容来自官方的用户手册,我这里专门的把这里的内容整理出一章主要是通过一些实例来帮助大家理解。
阿拉伯语、泰语或汉语等外语文本一般含有emWin标准字体以外的字符。
本章将介绍一些基本知识,比如定义全球所有可用字符的Unicode标准,以及UTF-8编码方案,emWin使用该方案来解码以Unicode字符编写的文本。同时还将说明如何启用阿拉伯语支持,以及如何采用Shift-JIS(日本工业标准)编码方案来显示文本。
17. 1 Unicode
17. 2 阿拉伯语支持
17. 3 泰语支持
17. 4 Shift JIS支持
17. 5 总结
17.1 Unicode
关于unicode的编码方面的知识在百度百科或者wiki百科上面有详尽的介绍,初学的一定要认真的看一下,了解这方面的知识对于以后学习大有裨益。这里我们主要的介绍一下UTF-8。
17.1.1 UTF-8 编码方案Unicode是国际组织制定的可以容纳世界上所有文字和符号的字符编码方案。Unicode用数字0-0x10FFFF来映射这些字符,最多可以容纳1114112个字符,或者说有1114112个码位。码位就是可以分配给字符的数字。UTF-8,UTF-16,UTF-32都是将数字转换到程序数据的编码方案。
ISO/IEC 10646-1定义了一种称为通用字符集(UCS)的多八位字符集,收入了全球大多数文字系统。然而,多八位字符并不兼容许多现有的应用程序和协议,因此就扩展出了一些各有特色的UCS转换格式(UTF)。
举个例子帮助大家理解,在Unicode中,汉字“字”对应的数字是23383(十进制),十六进制表示为0x5B57。在Unicode中,我们有很多方式将数字23383表示成程序中的数据,包括:UTF-8,UTF-16,UTF-32。UTF是“UCS Transformation Format”的缩写,可以翻译成Unicode字符集转换格式,即怎样将Unicode定义的数字转换成程序数据。例如,“汉字”对应的数字是0x6c49和0x5b57,而编码的程序数据是:
- chardata_utf8[]={0xE6,0xB1,0x89,0xE5,0xAD,0x97};//UTF-8编码
- char16_tdata_utf16[]={0x6C49,0x5B57};//UTF-16编码
- char32_tdata_utf32[]={0x00006C49,0x00005B57};//UTF-32编码
UTF-8具有多种特点,保留了全部ASCII字符,并且兼容依赖于ASCII值但对其他值透明的文件系统、解析器和其他软件。
在emWin中,UTF-8字符以1至3个八位字节序列编码。如果将高序位设为0,则剩下的7位将用来编码字符值。在一个由n个八位字节构成的序列中(n>1),起始八位字节第n个高序位设为1,其后一位设为0。该八位字节的剩余位用于存放待编码字符的值位。后续八位字节都将高序位设为1,其后一位设为0,各剩6位,用于保存待编码字符的值位。下表显示了编码范围:
为了说明UTF-8,这里给大家举一个例子,在emWin模拟器上面显示汉字“安富莱电子”,下面是在模拟器上面运行的代码(为了说明问题将所有的代码全部贴出)。
- #include "GUI.h"
-
- #ifndef GUI_CONST_STORAGE
- #define GUI_CONST_STORAGE const
- #endif
-
- /* The following line needs to be included in any file selecting the
- font.
- */
- extern GUI_CONST_STORAGE GUI_FONT GUI_Fontarmfly;
-
- /* Start of unicode area <CJK Unified Ideographs> */
- GUI_CONST_STORAGE unsigned char acGUI_Fontarmfly_5B50[ 93] = { /* code 5B50 */
- ________,________,________,
- ________,________,________,
- ________,________,________,
- ________,________,________,
- ________,________,________,
- ________,________,________,
- ________,________,________,
- ___XXXXX,XXXXXXXX,XXXXX___,
- ___XXXXX,XXXXXXXX,XXXXX___,
- ________,________,_XXXX___,
- ________,________,XXX_____,
- ________,______XX,X_______,
- ________,____XXXX,________,
- ________,___XXX__,________,
- ________,___XX___,________,
- ________,___XX___,________,
- XXXXXXXX,XXXXXXXX,XXXXXXXX,
- XXXXXXXX,XXXXXXXX,XXXXXXXX,
- ________,___XX___,________,
- ________,___XX___,________,
- ________,___XX___,________,
- ________,___XX___,________,
- ________,___XX___,________,
- ________,___XX___,________,
- ________,___XX___,________,
- ________,___XX___,________,
- ______XX,XXXXX___,________,
- ______XX,XXXX____,________,
- ________,________,________,
- ________,________,________,
- ________,________,________};
-
- GUI_CONST_STORAGE unsigned char acGUI_Fontarmfly_5B89[ 93] = { /* code 5B89 */
- ________,________,________,
- ________,________,________,
- ________,________,________,
- ________,________,________,
- ________,___X____,________,
- ________,__XXX___,________,
- ________,___XXX__,________,
- ________,____XX__,________,
- __XXXXXX,XXXXXXXX,XXXXXXX_,
- __XXXXXX,XXXXXXXX,XXXXXXX_,
- __X_____,________,_____XX_,
- __X_____,________,_____XX_,
- __X_____,__X_____,_____XX_,
- ________,_XX_____,________,
- ________,XX______,________,
- XXXXXXXX,XXXXXXXX,XXXXXXXX,
- XXXXXXXX,XXXXXXXX,XXXXXXXX,
- ______XX,________,XX______,
- ______XX,________,XX______,
- _____XX_,_______X,X_______,
- _____XXX,X_____XX,X_______,
- _______X,XXX__XXX,________,
- ________,_XXXXXX_,________,
- ________,__XXXXXX,________,
- ________,XXXX__XX,XX______,
- _____XXX,XXX_____,XXXX____,
- _XXXXXXX,________,__XXXX__,
- __XXX___,________,____X___,
- ________,________,________,
- ________,________,________,
- ________,________,________};
-
- GUI_CONST_STORAGE unsigned char acGUI_Fontarmfly_5BCC[ 93] = { /* code 5BCC */
- ________,________,________,
- ________,________,________,
- ________,________,________,
- ________,________,________,
- ________,________,________,
- ________,___X____,________,
- ________,___XX___,________,
- ________,___XX___,________,
- _XXXXXXX,XXXXXXXX,XXXXXXX_,
- _XX_____,________,_____XX_,
- _XX_____,________,_____XX_,
- _XX_XXXX,XXXXXXXX,XXX__XX_,
- _XX_____,________,________,
- _____XXX,XXXXXXXX,XXX_____,
- _____XX_,________,_XX_____,
- _____XX_,________,_XX_____,
- _____XXX,XXXXXXXX,XXX_____,
- _____XX_,________,_XX_____,
- ________,________,________,
- ___XXXXX,XXXXXXXX,XXXXX___,
- ___XX___,___XX___,___XX___,
- ___XX___,___XX___,___XX___,
- ___XXXXX,XXXXXXXX,XXXXX___,
- ___XX___,___XX___,___XX___,
- ___XX___,___XX___,___XX___,
- ___XX___,___XX___,___XX___,
- ___XXXXX,XXXXXXXX,XXXXX___,
- ___XX___,________,___XX___,
- ________,________,________,
- ________,________,________,
- ________,________,________};
-
- GUI_CONST_STORAGE unsigned char acGUI_Fontarmfly_7535[ 93] = { /* code 7535 */
- ________,________,________,
- ________,________,________,
- ________,________,________,
- ________,________,________,
- ________,________,________,
- ________,__XX____,________,
- ________,__XX____,________,
- ________,__XX____,________,
- __XXXXXX,XXXXXXXX,XXXXX___,
- __XXXXXX,XXXXXXXX,XXXXX___,
- __X_____,__XX____,___XX___,
- __X_____,__XX____,___XX___,
- __X_____,__XX____,___XX___,
- __X_____,__XX____,___XX___,
- __XXXXXX,XXXXXXXX,XXXXX___,
- __XXXXXX,XXXXXXXX,XXXXX___,
- __X_____,__XX____,___XX___,
- __X_____,__XX____,___XX___,
- __X_____,__XX____,___XX___,
- __X_____,__XX____,___XX___,
- __XXXXXX,XXXXXXXX,XXXXX___,
- __XXXXXX,XXXXXXXX,XXXXX___,
- __X_____,__XX____,______X_,
- __X_____,__XX____,_____XX_,
- ________,__XX____,_____XX_,
- ________,__XXXXXX,XXXXXXX_,
- ________,___XXXXX,XXXXXX__,
- ________,________,________,
- ________,________,________,
- ________,________,________,
- ________,________,________};
-
- GUI_CONST_STORAGE unsigned char acGUI_Fontarmfly_83B1[ 93] = { /* code 83B1 */
- ________,________,________,
- ________,________,________,
- ________,________,________,
- ________,________,________,
- ________,________,________,
- ________,________,________,
- _______X,_______X,X_______,
- _______X,_______X,X_______,
- _XXXXXXX,XXXXXXXX,XXXXXXXX,
- _XXXXXXX,XXXXXXXX,XXXXXXXX,
- _______X,_______X,X_______,
- ________,___XX___,________,
- __XXXXXX,XXXXXXXX,XXXXXX__,
- __XXXXXX,XXXXXXXX,XXXXXX__,
- _____X__,___XX___,__X_____,
- _____XX_,___XX___,_XX_____,
- ______XX,___XX___,XX______,
- ______XX,X__XX__X,X_______,
- _______X,___XX___,X_______,
- _XXXXXXX,XXXXXXXX,XXXXXXX_,
- _XXXXXXX,XXXXXXXX,XXXXXXX_,
- ________,_XXXXXX_,________,
- _______X,XX_XX_XX,________,
- _____XXX,X__XX__X,XX______,
- ___XXXX_,___XX___,_XXXX___,
- _XXXX___,___XX___,___XXXXX,
- _XX_____,___XX___,_____XX_,
- ________,___XX___,________,
- ________,________,________,
- ________,________,________,
- ________,________,________};
-
- GUI_CONST_STORAGE GUI_CHARINFO GUI_Fontarmfly_CharInfo[5] = {
- { 24, 24, 3, acGUI_Fontarmfly_5B50 } /* code 5B50 */
- ,{ 24, 24, 3, acGUI_Fontarmfly_5B89 } /* code 5B89 */
- ,{ 24, 24, 3, acGUI_Fontarmfly_5BCC } /* code 5BCC */
- ,{ 24, 24, 3, acGUI_Fontarmfly_7535 } /* code 7535 */
- ,{ 24, 24, 3, acGUI_Fontarmfly_83B1 } /* code 83B1 */
- };
-
- GUI_CONST_STORAGE GUI_FONT_PROP GUI_Fontarmfly_Prop5 = {
- 0x83B1 /* first character */
- ,0x83B1 /* last character */
- ,&GUI_Fontarmfly_CharInfo[ 4] /* address of first character */
- ,(GUI_CONST_STORAGE GUI_FONT_PROP *)0 /* pointer to next GUI_FONT_PROP */
- };
-
- GUI_CONST_STORAGE GUI_FONT_PROP GUI_Fontarmfly_Prop4 = {
- 0x7535 /* first character */
- ,0x7535 /* last character */
- ,&GUI_Fontarmfly_CharInfo[ 3] /* address of first character */
- ,&GUI_Fontarmfly_Prop5 /* pointer to next GUI_FONT_PROP */
- };
-
- GUI_CONST_STORAGE GUI_FONT_PROP GUI_Fontarmfly_Prop3 = {
- 0x5BCC /* first character */
- ,0x5BCC /* last character */
- ,&GUI_Fontarmfly_CharInfo[ 2] /* address of first character */
- ,&GUI_Fontarmfly_Prop4 /* pointer to next GUI_FONT_PROP */
- };
-
- GUI_CONST_STORAGE GUI_FONT_PROP GUI_Fontarmfly_Prop2 = {
- 0x5B89 /* first character */
- ,0x5B89 /* last character */
- ,&GUI_Fontarmfly_CharInfo[ 1] /* address of first character */
- ,&GUI_Fontarmfly_Prop3 /* pointer to next GUI_FONT_PROP */
- };
-
- GUI_CONST_STORAGE GUI_FONT_PROP GUI_Fontarmfly_Prop1 = {
- 0x5B50 /* first character */
- ,0x5B50 /* last character */
- ,&GUI_Fontarmfly_CharInfo[ 0] /* address of first character */
- ,&GUI_Fontarmfly_Prop2 /* pointer to next GUI_FONT_PROP */
- };
-
- GUI_CONST_STORAGE GUI_FONT GUI_Fontarmfly = {
- GUI_FONTTYPE_PROP /* type of font */
- ,31 /* height of font */
- ,31 /* space of font y */
- ,1 /* magnification x */
- ,1 /* magnification y */
- ,{&GUI_Fontarmfly_Prop1}
- ,25 /* Baseline */
- ,13 /* Height of lowercase characters */
- ,18 /* Height of capital characters */
- };
- void MainTask(void)
- {
- GUI_Init();
- GUI_SetFont(&GUI_Fontarmfly); (3)
- GUI_UC_SetEncodeUTF8(); /* required only once to activate UTF-8*/(4)
- GUI_DispString("\xe5\xae\x89\xe5\xaf\x8c\xe8\x8e\xb1\xe7\x94\xb5\xe5\xad\x90");
- while(1)
- {
- GUI_Delay(100);
- }
- }
1. 要注意这种数值的表达方式,具体定义如下:
#define ________ 0x00
#define _______X 0x01
#define ______X_ 0x02
#define ______XX 0x03
#define _____X__ 0x04
#define _____X_X 0x05
#define _____XX_ 0x06
#define _____XXX 0x07
#define ____X___ 0x08
#define ____X__X 0x09
#define ____X_X_ 0x0a
2. 后面的5B50就是汉字‘安’对象的Unicode吗,其它的类似。
3. 设置使用相应的字体。
4. 使能UTF-8解码,然后调用显示函数即可。
5. 上面字体编码的生成会在下期教程中跟大家详细讲解。
模拟器实际显示效果如下:
17.2 阿拉伯语支持
关于阿拉伯语的支持在emWin手册中有详细的讲解,这里就不跟大家再赘述了。在此跟大家演示一下官方做的例子。例子位置如下:
这个DEMO的主程序如下(没有贴前面的数据部分,只贴了主函数):
- /*******************************************************************
- *
- * Arabic and bidirectional text samples
- */
- static char * _apText[] = { (1)
- "\nBidirectional text\n\n\xd8\xb9\xd9\x84\xd8\xa7 1, 2, 345 \xd8\xba\xd9\x86\xd9\x8a XYZ \xd8\xa3\xd9\x86\xd8\xa7",
- "\nBeautiful\n\n\xd8\xac\xd9\x80\xd9\x85\xd9\x8a\xd9\x84",
- "\nI'm from Lebanon.\n\n\xd8\xa3\xd9\x86\xd8\xa7 \xd9\x85\xd9\x86 \xd9\x84\xd8\xa8\xd9\x86\xd8\xa7\xd9\x86",
- "\nI'm from Canada.\n\n\xd8\xa3\xd9\x86\xd8\xa7 \xd9\x85\xd9\x86 \xd9\x83\xd9\x86\xd8\xaf\xd8\xa7",
- "\nIsn't it like that?\n\n\xd8\xa3\xd9\x84\xd9\x8a\xd8\xb3 \xd9\x83\xd8\xb0\xd8\xa7\xd9\x84\xd9\x83\xd8\x9f",
- "\nDo you work?\n\n\xd9\x87\xd9\x84 \xd8\xaa\xd8\xb9\xd9\x85\xd9\x84\xd8\x9f",
- "\nThe book is heavy.\n\n\xd8\xa7\xd9\x84\xd9\x83\xd8\xaa\xd8\xa7\xd8\xa8 \xd8\xab\xd9\x82\xd9\x8a\xd9\x84",
- };
-
- /********************************************************************
- *
- * Static code
- *
- *********************************************************************
- */
- /*******************************************************************
- *
- * _ShowArabicTextSamples
- */
- static void _ShowArabicTextSamples(void) {
- GUI_RECT Rect = {40, 60, 279, 199};
-
- GUI_SetFont(&GUI_FontArabic24); // Set Arabic font(2)
- while (1) {
- unsigned i;
-
- GUI_SetColor(GUI_RED);(3)
- GUI_DrawRect(Rect.x0 - 1, Rect.y0 - 1, Rect.x1 + 1, Rect.y1 + 1);
- GUI_SetColor(GUI_WHITE);
- for (i = 0; i < GUI_COUNTOF(_apText); i++) {
- GUI_DispStringInRectWrap(_apText[i], &Rect, GUI_TA_HCENTER, GUI_WRAPMODE_WORD);
- GUI_Delay(2000);
- GUI_ClearRectEx(&Rect);
- }
- }
- }
-
- /********************************************************************
- *
- * Public code
- *
- *********************************************************************
- */
- /********************************************************************
- *
- * MainTask
- */
- void MainTask(void) {
- GUI_Init();
- GUI_UC_SetEncodeUTF8(); // Enable UTF8 decoding(4)
- GUI_UC_EnableBIDI(1); // Enable bidirectional text (5)
- //
- // Lable the sample
- //
- GUI_SetFont(&GUI_Font24_ASCII);
- GUI_DispStringHCenterAt("Arabic language sample", 160, 5);
- //
- // Call demo loop
- //
- _ShowArabicTextSamples();
- }
1. ‘\’号后面数字是通过官方的U2C小工具生成的,生成方面在官方的手册中有讲解。这个小软件的主要功能就是将UTF-8格式的文本转换为C编码。
2. 设置使用阿拉伯字体。
3. 画一个红色的小方框.。
4. 使能UTF-8解码。
5. 由于西方语言与阿拉伯语之间的根本差异在于,阿拉伯语是从右往左写的,而且不区分大小写。而默认情况下,emWin始终从左到右写文本,不会进行上述阿拉伯语字符转换操作。如果要启用对双向文本和阿拉伯字符转换的支持,则必须在应用中添加以这行代码。
启用后,emWin会遵循统一码联盟规定的双向算法规则,以在绘制文本前获得正确的视觉顺序。
实际显示效果如下(动态的,这里只贴了一幅):
17.3 泰语支持
关于泰语语的支持在emWin手册中有详细的讲解,这里就不跟大家再赘述了。在此跟大家演示一下官方做的例子。例子位置如下:
这个DEMO的主程序如下(没有贴前面的数据部分,只贴了主函数):
- /*******************************************************************
- *
- * Thai text samples
- */
- static char * _apText[] = {
- "How are you?\n\xe0\xb8\xaa\xe0\xb8\x9a\xe0\xb8\xb2\xe0\xb8\xa2\xe0\xb8\x94\xe0\xb8\xb5\xe0\xb8\xab\xe0\xb8\xa3\xe0\xb8\xb7\xe0\xb8\xad",
- "Fine, and you?\n\xe0\xb8\xaa\xe0\xb8\x9a\xe0\xb8\xb2\xe0\xb8\xa2\xe0\xb8\x94\xe0\xb8\xb5 \xe0\xb9\x81\xe0\xb8\xa5\xe0\xb9\x89\xe0\xb8\xa7\xe0\xb8\x84\xe0\xb8\xb8\xe0\xb8\x93\xe0\xb8\xab\xe0\xb8\xa5\xe0\xb9\x88\xe0\xb8\xb0\xe0\xb8\x84\xe0\xb8\xa3\xe0\xb8\xb1\xe0\xb8\x9a",
- "Nice to meet you.\n\xe0\xb8\xa2\xe0\xb8\xb4\xe0\xb8\x99\xe0\xb8\x94\xe0\xb8\xb5\xe0\xb8\x97\xe0\xb8\xb5\xe0\xb9\x88\xe0\xb9\x84\xe0\xb8\x94\xe0\xb9\x89\xe0\xb8\xa3\xe0\xb8\xb9\xe0\xb9\x89\xe0\xb8\x88\xe0\xb8\xa3\xe0\xb8\xb1\xe0\xb8\x81",
- "You're welcome.\n\xe0\xb9\x84\xe0\xb8\xa1\xe0\xb9\x88\xe0\xb9\x80\xe0\xb8\x9b\xe0\xb9\x87\xe0\xb8\x99\xe0\xb9\x84\xe0\xb8\xa3",
- "I can't speak Thai\n\xe0\xb8\x9e\xe0\xb8\xb9\xe0\xb8\x94\xe0\xb8\xa0\xe0\xb8\xb2\xe0\xb8\xa9\xe0\xb8\xb2\xe0\xb9\x84\xe0\xb8\x97\xe0\xb8\xa2\xe0\xb9\x84\xe0\xb8\xa1\xe0\xb9\x84\xe0\xb8\x94",
- "Do you speak English?\n\xe0\xb8\x9e\xe0\xb8\xb9\xe0\xb8\x94\xe0\xb8\xa0\xe0\xb8\xb2\xe0\xb8\xa9\xe0\xb8\xb2\xe0\xb8\xad\xe0\xb8\xb1\xe0\xb8\x87\xe0\xb8\x81\xe0\xb8\xa4\xe0\xb8\xa9\xe0\xb9\x84\xe0\xb8\x94\xe0\xb9\x89\xe0\xb9\x84\xe0\xb8\xab\xe0\xb8\xa1",
- "Thank you very much.\n\xe0\xb8\x82\xe0\xb8\xad\xe0\xb8\x9a\xe0\xb8\x84\xe0\xb8\xb8\xe0\xb8\x93\xe0\xb8\xa1\xe0\xb8\xb2\xe0\xb8\x81",
- "How do you say this in Thai?\n\xe0\xb8\x9e\xe0\xb8\xb9\xe0\xb8\x94\xe0\xb9\x80\xe0\xb8\x9b\xe0\xb9\x87\xe0\xb8\x99\xe0\xb8\xa0\xe0\xb8\xb2\xe0\xb8\xa9\xe0\xb8\xb2\xe0\xb9\x84\xe0\xb8\x97\xe0\xb8\xa2\xe0\xb8\xad\xe0\xb8\xa2\xe0\xb9\x88\xe0\xb8\xb2\xe0\xb8\x87\xe0\xb9\x84\xe0\xb8\xa3",
- };
-
- /********************************************************************
- *
- * Static code
- *
- *********************************************************************
- */
- /*******************************************************************
- *
- * _ShowThaiTextSamples
- */
- static void _ShowThaiTextSamples(void) {
- GUI_RECT Rect = {100, 60, 219, 199};
- GUI_SetFont(&GUI_FontCordiaNew32); // Set thai font
- while (1) {
- unsigned i;
- GUI_SetColor(GUI_RED);
- GUI_DrawRect(Rect.x0 - 1, Rect.y0 - 1, Rect.x1 + 1, Rect.y1 + 1);
- GUI_SetColor(GUI_WHITE);
- for (i = 0; i < GUI_COUNTOF(_apText); i++) {
- GUI_DispStringInRectWrap(_apText[i], &Rect, GUI_TA_HCENTER, GUI_WRAPMODE_WORD);
- GUI_Delay(2000);
- GUI_ClearRectEx(&Rect);
- }
- }
- }
-
- /********************************************************************
- *
- * Public code
- *
- *********************************************************************
- */
- /********************************************************************
- *
- * MainTask
- */
- void MainTask(void) {
- GUI_Init();
- GUI_UC_SetEncodeUTF8(); // Enable UTF8 decoding
- //
- // Lable the sample
- //
- GUI_SetFont(&GUI_Font24_ASCII);
- GUI_DispStringHCenterAt("Thai language sample", 160, 5);
- //
- // Call demo loop
- //
- _ShowThaiTextSamples();
- }
这个程序和上面的阿拉伯语支持基本是一样的,显示效果如下:
17..4 Shift JIS支持
Shift JIS(日本工业标准)是一种针对日语的字符编码方法。这是最常用的日语编码方法。Shift JIS编码大量使用8位字符,第一个字节的值用于区分单字节字符和多字节字符。仅当需要转换采用Shift JIS编码文本时,才需要emWin支持Shift JIS。绘制Shift JIS字符串时无需调用特殊函数。关键是要有一个含有Shift JIS字符的字体文件。
字体转换器可以从任意Windows字体产生Shift JIS字体,以供emWin使用。使用Shift JIS字体时,用于显示Shift JIS字符的函数会自动与字体库链接。
这部分知识大家可以看一下官网的演示例子进行详细了解。
17.5 总结本期教程大家重点的了解一下Unicode编码方面的知识,这部分知识很重要,其它的语言支持做个了解即可,用到的时候再做研究。