嵌入式系统多语言文本解决方案

作者:李智敏,华清远见嵌入式学院上海中心讲师。

在嵌入式系统开发中,某些产品可能会需要跨区域销售,因此,通常会有多语言的需求。对于这一类多语言需求的解决,在嵌入式产品中有其特殊的地方。以下,给出一种可能的解决方案。

该方案的核心思想是为所有文本建立索引,通过索引可以得到特定语言的文字编码,随后通过该编码获得字库资源,并进行输出。在这过程中,唯一需要注意的是对于特殊的某些语言,如阿拉伯语等的处理。(阿拉伯语字符在连写时,其形状会发生变化。)

1. 字库的建立:

文本最终都将输出给用户,因此,必须为文本内容指定字库。本方案中采用UNICODE编码字库。字库文件采用二进制存储,按UNICODE编码顺序排列存储点阵数据,点阵大小为24*24。

2. 文本资源文件:

文本资源文件描述了特定语言的文本内容,以及相关的字符编码。例如对于Chinese.cfg文件来说,就保留了一个索引为1的文本,该文本内容为“确认”;相应对于English.cfg文件来说,必然会同样有一个索引为1的文本,该文本内容为“Confirm”。通过对所有的文本建立索引并生成文本资源文件,就为最终的解决扫清了障碍。

文本资源文件采用二进制存储。文件头部16个字节为描述性信息,之后是文本映射表,紧跟映射表之后为文本的实际Unicode编码。

3. 对文本资源文件进行描述的数据结构

typedef struct _txtres_fileheader {
            LONG lFileType; //文件类型,0x2E434647='.CFG'
            LONG lVersionNum; //适用版本,0x56313032='V102'
            LONG lMapOffset; //偏移量,文件头到文本映射区的偏移量
            LONG lDataOffset; //偏移量,文件头到文本数据区的偏移量
        } APPTEXT_FILEHEADER;

4. 文本映射表结构

typedef struct _txtres_txtmap {
            WORD wTextIndes; //当前文本的索引值
            WORD wTextSize; //当前文本的Unicode编码所占用的字节数
            LONG lUnicodeOffset; //从文件头到当前文本Unicode编码存储位置的偏移量
        } TXTRES_TXTMAP;

5. 特殊语言(阿拉伯语等)的解决

特殊语言在连写时可能发生变化,因此采用固定字库可能无法解决该问题。针对这种状况可以直接新增一个自定义字库。以阿拉伯语为例,该字库的处理过程如下:

a. 首先将阿拉伯的文本内容按预定格式(例如24*24)在windows系统上显示输出,并将内容保存为图片格式。此时图片中便为连写内容。
        b. 随后,对图片进行分割。如按照24*24进行分割便可得到特定的24*24大小的字库内容。
        c. 最后,将原先的UNICODE编码转为按照之前生成的字库来编码。
        d. 之后在程序代码中就可利用自定义字库与自定义编码来显示阿拉伯语。

最后附上部分示例代码。

//定义文本配置文件路径
        #define TXT_FILE_ENGLISH "config/English.cfg"
        #define TXT_FILE_CHINASIM "config/ChinaSim.cfg"
        #define TXT_FILE_CHINATRA "config/ChinaTra.cfg"
        #define TXT_FILE_KOREAN "config/Korean.cfg"
        #define TXT_FILE_JAPANESE "config/Japanese.cfg"
        #define TXT_FILE_SPANISH "config/Spanish.cfg"
        #define TXT_FILE_RUSSIAN "config/Russian.cfg"
        #define TXT_FILE_THAI "config/Thai.cfg"
        #define TXT_FILE_GERMAN "config/German.cfg"
        #define TXT_FILE_FRANCE "config/France.cfg"
        #define TXT_FILE_ITALY "config/Italy.cfg"
        #define TXT_FILE_ARABIA "config/Arabia.cfg"
        #define TXT_FILE_PORTUGAL "config/Portugal.cfg"
        #define TXT_FILE_HINDI "config/Hindi.cfg"
        #define TXT_FILE_TURKISH "config/Turkish.cfg"
        #define TXT_FILE_VIETNAM "config/Vietnam.cfg"
        #define TXT_FILE_SWIDISH "config/Swedish.cfg"
        #define TXT_FILE_POLISH "config/Polish.cfg"

//根据文本索引及文本语言,读取相应的文本配置文件,以得到该文本,成功返回有效指针

GUISTRING * GetTextResource(LONG lIndex, LONG lLanguage)
        {
                GUISTRING * pTxt;
                APPTEXT_FILEHEADER fh;
                APPTEXT_MAPPING map;
                STRING strFile;
                WORD * pBuf;
                int fd, iOff;

        //确定要读取的配置文件
                switch (lLanguage)
                {
                case TXT_LANG_ENGLISH:
                        strFile = TXT_FILE_ENGLISH;
                        break;
                case TXT_LANG_CHINASIM:
                        strFile = TXT_FILE_CHINASIM;
                        break;
                case TXT_LANG_CHINATRA:
                        strFile = TXT_FILE_CHINATRA;
                        break;
                case TXT_LANG_KOREAN:
                        strFile = TXT_FILE_KOREAN;
                        break;
                case TXT_LANG_JAPANESE:
                        strFile = TXT_FILE_JAPANESE;
                        break;
                case TXT_LANG_SPANISH:
                        strFile = TXT_FILE_SPANISH;
                        break;
                case TXT_LANG_RUSSIAN:
                        strFile = TXT_FILE_RUSSIAN;
                        break;
                case TXT_LANG_THAI:
                        strFile = TXT_FILE_THAI;
                        break;
                case TXT_LANG_GERMAN:
                        strFile = TXT_FILE_GERMAN;
                        break;
                case TXT_LANG_FRANCE:
                        strFile = TXT_FILE_FRANCE;
                        break;
                case TXT_LANG_ITALY:
                        strFile = TXT_FILE_ITALY;
                        break;
                case TXT_LANG_ARABIA:
                        strFile = TXT_FILE_ARABIA;
                        break;
                case TXT_LANG_PORTUGAL:
                        strFile = TXT_FILE_PORTUGAL;
                        break;
                case TXT_LANG_HINDI:
                        strFile = TXT_FILE_HINDI;
                        break;
                case TXT_LANG_TURKISH:
                        strFile = TXT_FILE_TURKISH;
                        break;
                case TXT_LANG_VIETNAM:
                        strFile = TXT_FILE_VIETNAM;
                        break;
                case TXT_LANG_SWIDISH:
                        strFile = TXT_FILE_SWIDISH;
                        break;
                case TXT_LANG_POLISH:
                        strFile = TXT_FILE_POLISH;
                        break;
                default:
                        return NULL;
                }

        //打开配置文件并检查其格式
                if ((fd = open(strFile, O_RDONLY)) == -1)
                {
                        return NULL;
                }
                if (read(fd, &fh, 16) != 16)
                {
                        close(fd);
                        return NULL;
                }
                if (fh.lFileType != 0x4746432E || fh.lVersionNum != 0x32303156)
                {
                        close(fd);
                        return NULL;
                }

        //在文本映射区内查找匹配的文本索引
                for (iOff = fh.lMapOffset; iOff < fh.lDataOffset; iOff += 8)
                {
                        if (read(fd, &map, 8) != 8)
                        {
                                close(fd);
                                return NULL;
                        }
                        if (map.wTextIndex == lIndex)
                        {
                                break;
                        }
                }
                if (iOff >= fh.lDataOffset)
                {
                        close(fd);
                        return NULL;
                }

        //根据找到的文本映射来读取文本内容
                if (!(pBuf = GuiMemAlloc(map.wTextSize + 2)))
                {
                        close(fd);
                        return NULL;
                }
                lseek(fd, fh.lDataOffset + map.lTextOffset, SEEK_SET);
                if (read(fd, pBuf, map.wTextSize) != map.wTextSize)
                {
                        GuiMemFree(pBuf);
                        close(fd);
                        return NULL;
                }
                pBuf[map.wTextSize >> 1] = 0;

        //建立字符串对象
                pTxt = CreateStringDirect(pBuf);
                GuiMemFree(pBuf);
                close(fd);

        return pTxt;
        }

//定义与字符串相关的数据结构
        #ifndef GUI_STRING_STRUCT
        typedef struct _string
        {
                WORD wWidth; //字符串宽度,字符串输出时的总点阵宽度
                WORD wLength; //字符串长度,不包括'/0'
                WORD * pContent; //字符串内容,以'/0'结尾
        } GUISTRING;
        //结束与字符串相关的数据结构的定义
        #define GUI_STRING_STRUCT
        #endif

/***
                * 功能:
                        根据指定的信息直接建立字符串,函数返回字符串指针
                * 参数:
                        1.WORD * pContent: 字符串内容
                * 返回:
                        成功返回字符串指针
                        失败返回NULL
                * 备注:

***/
        GUISTRING * CreateStringDirect(WORD * pContent)
        {
                GUISTRING * pStr;

        //尝试为字符串分配内存
                if (!(pStr = GuiMemAlloc(sizeof(GUISTRING))))
                {
                        PRINT_INF(CreateStringDirect Err0!);
                        return NULL;
                }
                //字符串内容为空,建立一个空字符串对象
                if (!pContent)
                {
                        pStr->wWidth = 0;
                        pStr->wLength = 0;
                        pStr->pContent = NULL;
                        return pStr;
                }
                //统计字符串长度
                pStr->wLength = 0;
                pStr->pContent = pContent;
                while (*pStr->pContent++)
                {
                        pStr->wLength++;
                }
                //尝试为字符串内容分配内存
                if (!(pStr->pContent = GuiMemAlloc((pStr->wLength + 1) << 1)))
                {
                        GuiMemFree(pStr);
                        PRINT_INF(CreateStringDirect Err1!);
                        return NULL;
                }
                //写入字符串内容
                memcpy(pStr->pContent, pContent, (pStr->wLength + 1) << 1);
                //计算字符串宽度
                if (_StringObjectFill(pStr))
                {
                        GuiMemFree(pStr->pContent);
                        GuiMemFree(pStr);
                        PRINT_INF(CreateStringDirect Err2!);
                        return NULL;
                }

        return pStr;
        }

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
v1.11 (08/14/2012) 1. 增加注册年限选择。 v1.10 (06/26/2012) 1. 精简字库检索表。 2. 增加 GBK 字库输出。 3. 增加一种点阵数据存储格式(只存有效像素数据--not fixed, 不支持MBCS编码格式的中日韩), 对泰文,缅甸文等特殊语种显示非常便捷。 v1.09 (06/15/2012) 1. 增加输出 C 语言(数组) 字体格式。 V1.08 (05/17/2012) 1. 增加了两个版本(免费和试用版) 免费版 只对 16点阵有效。 试用版 对所有点阵有效,但是会缺部分字符。 2. 增加热键功能。 3. 修改了多国语言生成.h文件时,start 与 end 不匹配的bug。 4. 完善文档《GuiTool 使用说明》, 增加更多图解说明。 文档下载地址: http://ishare.iask.sina.com.cn/f/24472766.html v1.07 (05/02/2012) 1. 修改注册方式(改为文件)。 2. 增加bdf格式编码过滤功能,主要是为了支持 MTK 手机点阵字库。 3. 增加xp控件属性。 4. 增加扫描模式图解。 5. 修改了 bdf 2 bin 的一个bug。(选择输出位图时,会输出n个位图文件) 6. 修改了 BDF 文件中当字符显示宽度为0,存位图(所有字符存一张图片)失败的错误。 v1.06 (04/10/2012) 1. 增加系统字体支持,操作更简便,快捷。 枚举所有已安装系统字体,直接选择即可。 v1.05 (03/24/2012) Fontmaker(点阵字库) 1. 修正了字符对齐问题。 2. 增加了单个字符或多个字符输出成位图文件设定。 3. 完善了阿拉伯文字库(unicode 字库有效)。 4. 增加自定义字符功能(unicode 字库有效)。 Multi-language(多国语言) 1. 增加输出编码格式 (mbcs, utf16-lb, utf8)设置 2. 增加数组格式输出。 Image Manager(图像管理) 1. 该页为新增功能,支持图片图像的数据转换。主要应用在做产品logo图片方面。 V1.04 (07/16/2011) 1. 增加了一个字符串mbcs2unicode(内码转统一码)的功能。 (支持转:U16-LE, U16-BE, UTF8) V1.03 (07/05/2011) 1. 修改了 Example 中点阵字库解析源码,更加便于移植。(基本做到只需修改font_file.c 即可) 2. 修改了内码(MBCS)字库点阵信息读取的一个错误。 3. 增加了多语言支持(简中,英文),还有待完善。。。 V1.02 (07/01/2011) 1. FontMaker V2.03 a. 增加字符宽高比调节(HorR & VerR) b. 增加对*.ttc 字库的支持。 c. 增加bdf(*.bdf)文件格式转Simple Unicode编码格式的bin文件。 V1.01 (06/29/2011) 1. FontMaker V2.02 a. 增加了 Simple Unicode功能。(适合小字库) b. 增加了 “扫描方向及反显”设置。 2. Multi-Language V1.01 a. 修改了除 office 2000 外,其它不能支持的问题。 V1.00: (2007-2011) 1. 继承 FontMaker V2.01 的所有功能。 2. 增加了一个 Multi-Languge V1.00 的打包转换功能。 FontMaker 基本功能: 1.支持所有 windows 字符集:CP932(日文Shift-JIS)CP936(简体中文GBK)CP949(韩文)CP950(繁体中文 Big5),CP874(泰文),CP1250(中欧)CP1251(西里尔文),CP1252(西欧--"拉丁文I"),CP1253(希腊文), CP1254(土耳其文),CP1255(希伯来文),CP1256(阿拉伯文),CP1257(波罗的海文),CP1258(越南) 2.支持非等宽字库。 3.支持BIN,TXT,BMP,BDF 文件输出。 4.支持unicode字库输出,即可以做到在一个窗口中同时显示多国语言(文字) 5.支持单个字符编辑,预览(所见即所得)。 6.支持字库文件和输出路径记忆功能. 7. 支持从bdf格式转换自定义字库(bin文件)格式。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值